diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5609304 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,81 @@ +# EditorConfig: https://editorconfig.org +# In VS Code, install the "EditorConfig for VS Code" extension (EditorConfig.EditorConfig). + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{py,pyi}] +indent_size = 4 +max_line_length = 88 + +[*.{mojo,🔥}] +indent_size = 4 +max_line_length = 88 + +[*.rs] +indent_size = 4 +max_line_length = 100 + +[{Cargo.toml,Cargo.lock,rustfmt.toml,.rustfmt.toml,clippy.toml}] +indent_size = 4 + +[{mojoproject.toml,pixi.toml,pixi.lock}] +indent_size = 4 + +[*.{yml,yaml}] +indent_size = 2 + +[*.{json,jsonc,json5}] +indent_size = 2 + +[*.sql] +indent_style = space +indent_size = 2 + +[*.{js,jsx,mjs,cjs,ts,tsx,css,scss,less,html,vue,svelte}] +indent_size = 2 + +[*.{toml,ini,cfg}] +indent_size = 4 + +[*.xml] +indent_size = 2 + +[*.{md,markdown}] +indent_size = 2 +trim_trailing_whitespace = false + +[*.{sh,bash,zsh}] +indent_size = 2 + +[{Makefile,makefile,*.mk}] +indent_style = tab + +[*.go] +indent_style = tab + +[*.{bat,cmd,ps1}] +end_of_line = crlf + +[{Dockerfile,Dockerfile.*,*.dockerfile}] +indent_size = 4 + +[*.{tf,tfvars,hcl}] +indent_size = 2 + +[LICENSE*] +insert_final_newline = false + +[*.{diff,patch}] +trim_trailing_whitespace = false + +[*.min.{js,css}] +insert_final_newline = unset +trim_trailing_whitespace = unset diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7d23aca --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto eol=lf +# Generated data: exact bytes matter, and diffs are by line. +vectors/** -text diff +fixtures/** -text diff +fixtures/**/*.png binary +# The pixi lock file: generated, highlighted as YAML, never merged line by line. +pixi.lock merge=binary linguist-language=YAML linguist-generated=true diff --git a/.gitea/workflows/check.yml b/.gitea/workflows/check.yml new file mode 100644 index 0000000..08bfc36 --- /dev/null +++ b/.gitea/workflows/check.yml @@ -0,0 +1,21 @@ +# Forgejo and Gitea Actions both read .github/workflows when their own folder is absent. +# On Forgejo, if the runner's default action mirror lacks setup-pixi, write it as +# https://github.com/prefix-dev/setup-pixi@v0.9.4. +# The tools need Python 3.14, which pixi.toml pins, so one environment covers every supported Python. +name: check +on: + push: + branches: [main] + pull_request: + +jobs: + check: + runs-on: linux-base + container: + image: git.scient.ing/infra/linux-base:26.10.7 + steps: + - uses: actions/checkout@v4 + - name: Check the repository + run: pixi run check + - name: Stress the reference implementation + run: pixi run python tools/stress.py diff --git a/.gitea/workflows/site.yml b/.gitea/workflows/site.yml new file mode 100644 index 0000000..8ab2f56 --- /dev/null +++ b/.gitea/workflows/site.yml @@ -0,0 +1,59 @@ +# Builds and checks the website on every push to main, and publishes it to /srv/www/paperspec; see deploy/README.md. +# The linux-base runner mounts the host's /srv/www into its job containers, so publishing is a local copy. +name: site +on: + push: + branches: [main] + workflow_dispatch: +permissions: + contents: read +concurrency: + group: site-publish + cancel-in-progress: false +defaults: + run: + shell: bash +env: + SITE_ROOT: /srv/www + SITE_SLUG: paperspec +jobs: + site: + runs-on: linux-base + container: + image: git.scient.ing/infra/linux-base:26.10.7 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Restore the environment + uses: actions/cache@v4 + with: + path: .pixi/envs + key: pixi-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('pixi.lock') }} + restore-keys: pixi-${{ runner.os }}-${{ runner.arch }}- + - name: Install the environment + run: pixi install --locked + - name: Check the repository and the site + run: pixi run --frozen quick + - name: Build the site + run: pixi run --frozen site --out _site + - name: Publish the site + if: github.ref == 'refs/heads/main' + run: | + if [ ! -d "$SITE_ROOT" ]; then + echo "$SITE_ROOT is not mounted on this runner, so the site was built and checked but not published." + exit 0 + fi + case "$SITE_SLUG" in + ''|*/*|.*) echo "SITE_SLUG must be a plain folder name, not '$SITE_SLUG'." >&2; exit 1 ;; + esac + if [ ! -f _site/index.html ] || [ ! -f _site/404.html ]; then + echo "_site/ has no index.html or 404.html, so it was not published." >&2 + exit 1 + fi + # --checksum without --times leaves unchanged files untouched, so their Last-Modified and ETag stay valid + # in caches; --delay-updates and --delete-delay apply the changes together at the end of the copy, and + # --chmod keeps every file readable by the web server whatever the container's umask. + rsync --recursive --links --perms --chmod=D755,F644 --checksum --delay-updates --delete-delay --stats \ + _site/ "$SITE_ROOT/$SITE_SLUG/" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..856c31e --- /dev/null +++ b/.gitignore @@ -0,0 +1,764 @@ +__pycache__/ +*.pyc +*.db +*.db.assets/ + +# the website, built by tools/site.py +/_site/ + +# pixi environments +.pixi/* +!.pixi/config.toml + + +# Created by https://www.toptal.com/developers/gitignore/api/osx,python,pycharm,windows,visualstudio,visualstudiocode,zsh,jetbrains,jupyternotebooks +# Edit at https://www.toptal.com/developers/gitignore?templates=osx,python,pycharm,windows,visualstudio,visualstudiocode,zsh,jetbrains,jupyternotebooks + +### JetBrains ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### JetBrains Patch ### + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### JupyterNotebooks ### +# gitignore template for Jupyter Notebooks +# website: http://jupyter.org/ + +.ipynb_checkpoints +*/.ipynb_checkpoints/* + +# IPython +profile_default/ +ipython_config.py + +### OSX ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.claude + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Zsh ### +# Zsh compiled script + zrecompile backup +*.zwc +*.zwc.old + +# Zsh completion-optimization dumpfile +*zcompdump* + +# Zsh history +.zsh_history + +# Zsh sessions +.zsh_sessions + +# Zsh zcalc history +.zcalc_history + +# A popular plugin manager's files +._zinit +.zinit_lstupd + +# zdharma/zshelldoc tool's files +zsdoc/data + +# robbyrussell/oh-my-zsh/plugins/per-directory-history plugin's files +# (when set-up to store the history in the local directory) +.directory_history + +# MichaelAquilina/zsh-autoswitch-virtualenv plugin's files +# (for Zsh plugins using Python) + +# Zunit tests' output +/tests/_output/* +!/tests/_output/.gitkeep + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +*.code-workspace + +# Local History for Visual Studio Code + +# Windows Installer files from build outputs + +# JetBrains Rider +*.sln.iml + +### VisualStudio Patch ### +# Additional files built by Visual Studio + +# End of https://www.toptal.com/developers/gitignore/api/osx,python,pycharm,windows,visualstudio,visualstudiocode,zsh,jetbrains,jupyternotebooks + +# The Visual Studio rules above ignore every packages/ and log/ folder; these hold fixtures that tools/check.py +# compares byte for byte, so keep them. +!/fixtures/packages/* +!/fixtures/records/log/ diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 0000000..f0cc062 --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,5 @@ +{ + // Which files markdownlint-cli2 checks; the rules themselves are in .markdownlint.jsonc. + "globs": ["**/*.md"], + "ignores": [".pixi/**", "node_modules/**", "_site/**"] +} diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 0000000..ed7120f --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,9 @@ +{ + // One sentence per line makes long lines normal, and tables are wide. + "MD013": false, + // The chapters use the same subheadings in different sections. + "MD024": { "siblings_only": true }, + // Numbered algorithm steps keep their numbers. + "MD029": { "style": "ordered" }, + "MD033": false +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d872cd0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +A change to any computed value is a breaking change and needs a new major version of the format it touches; see [spec/00-introduction.md](spec/00-introduction.md). + +## 0.1.0 + +The first release. + +- The specification, in chapters 0 to 23, covering every format: 32 formats, of which 19 are `candidate` and 13 `provisional`. +- 42 JSON Schemas, using a keyword subset that independent validators read alike. +- Tables for SQLite, Dolt and PostgreSQL, a team's store, and the SQLite bundle with full-text search. +- The JSON-LD context for layers, and registries of formats, rules, download-stamp rules and default stage requirements. +- Test vectors for every computed value, from canonical JSON to anchor resolution, grading and the target set of targeted F3. +- Example packages (a converted chemistry paper with corrections and receipts, its checks-only export, an open-access paper, a Typst draft and a tiny document, also as a zip), a record of every other format, and 31 broken packages, each breaking one named rule. +- Work keys minted from a Scholar-style citation key and a hash of the work's identity, with document keys for versions; `tag:` URIs for layers, annotations and documents. +- Spot-check seeds as VRF proofs (RFC 9381), RFC 9162 inclusion and consistency proofs, a history root over every document's corrections, and a provisional transparency log with signed checkpoints. +- Signed QA reports, a conformance checklist covered by a receipt, and a `description` annotation for the figure descriptions an accessible export needs. +- ML-DSA-65 (FIPS 204) as a signature scheme, with a reference implementation checked against NIST's vectors; `cose` reserved; `did:key` identifiers for roster keys; the hash algorithm named in every document; model provenance by weights, prompt and parameters; witnesses and a static tile layout for the log; and the character data pinned to Unicode 16.0. +- Guides for newcomers: an overview, the concepts, a walkthrough of the example paper, runnable examples, the rationale, a FAQ and a glossary. +- Tools that build and check everything, validate packages and zipped packages and run proposed corrections through the gate, load packages into SQLite or a bundle, and stress the reference implementation with random inputs. +- A pixi workspace pinned to Python 3.14, with tasks for checking, building, linting, validating and loading. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d3d2acb --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,59 @@ +# Contributing + +This page is for anyone who wants to fix the specification, change a format or add an example. +Propose a change as a pull request on the repository at . + +## What a change needs + +A change starts in the chapter of [the specification](spec/README.md) that defines the rule, because the chapters are normative. +The schemas, SQL, registries, vectors and fixtures then follow the chapter ([spec/00 §0.5](spec/00-introduction.md#05-how-the-repository-is-arranged)). + +1. **Change the chapter.** + Say what is new in the chapter's own terms, and link the sections it touches. +2. **Change the schemas, SQL and registries** that the rule shapes. + A new refusal gets a rule ID in [registry/rules.json](registry/rules.json). +3. **Compute, never type, the expected values.** + Change the oracle in [tools/oracle/](tools/oracle/) to apply the rule, and add the case that shows it to [tools/build.py](tools/build.py): a vector, a fixture or a broken package in `fixtures/invalid/`. + Then run `pixi run build`, which rewrites `fixtures/` and `vectors/`. +4. **Run the checks.** + `pixi run check` must end with `All checks pass.` + Without pixi, run `python3 tools/check.py`, with Python 3.14 and two packages, `jsonschema` and `cryptography` installed. +5. **Record the change** in [CHANGELOG.md](CHANGELOG.md). + +## Versions + +A change that makes a valid file invalid, or that changes a computed value, is a breaking change and needs a new major version of the format, with a migration. +Adding an optional property, a node kind, a run kind or an enumeration value is a minor change ([spec/00 §0.3](spec/00-introduction.md#03-format-identifiers-and-versions)). +A rebuild that changes any file under `vectors/` or any hash in `fixtures/` is a computed value changing, so say in the pull request why it must. + +## New node kinds and run kinds + +Propose a kind with the vector or fixture that shows it. +A node kind needs its row in [chapter 3](spec/03-nodes.md), the node schema, and its entry in the `CHILDREN` table of `tools/oracle/model.py`. +A run kind needs its row in [section 3.5](spec/03-nodes.md#35-inline-runs) and the node schema, and its text in the plain projection ([3.6](spec/03-nodes.md#36-the-plain-projection)) and in the strict and lossy projections ([5.3](spec/05-hashes.md#53-the-strict-projection), [5.5](spec/05-hashes.md#55-the-lossy-projection)). + +## Releasing + +A release is a tag on `main` whose version is the top heading of [CHANGELOG.md](CHANGELOG.md). +Before tagging: + +1. `pixi run check` passes on Linux and macOS, which the workflow in `.gitea/workflows/` runs on every push. + The check also confirms that every count the prose states (formats, schemas, vectors, broken packages) matches the repository, and that `pixi.toml`, the registries and `tools/build.py` state the same version. +2. `python3 tools/stress.py` passes with its default seed, and with one or two others. +3. The website is published from the release ([deploy/](deploy/README.md)), and the JSON-LD context at `https://paperspec.scient.ing/context/scienting-1.jsonld` and a schema at its `$id` both answer with their media types. + Layers claim to be W3C Web Annotations, and a JSON-LD processor that cannot fetch the context cannot read them. +4. The decisions that freeze on release are made: enumeration values and format identifiers never change meaning afterwards ([spec/22 §22.5](spec/22-conformance.md#225-stability)), so a name worth changing is changed now. +5. The CHANGELOG entry describes the release in the terms of the chapters it touches. + +## Writing + +The checker enforces two rules on every Markdown file: one sentence per line, and US spelling. +`pixi run lint` runs markdownlint with the repository's settings. +Define each term where it first appears, because the guides and READMEs are written for newcomers as well as implementers. + +All fixture text is synthetic, written for the fixtures. +The keys in `fixtures/keys/` are public test keys and must never sign anything else. + +## Licenses + +Each path keeps the license that [LICENSE.md](LICENSE.md) gives it: prose CC-BY-4.0, the normative data CC0-1.0, and `tools/` Apache-2.0. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..dc63081 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,17 @@ +# Licenses + +| Paths | License | SPDX | +| --- | --- | --- | +| `spec/`, `docs/`, `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md` and the other prose | Creative Commons Attribution 4.0 International | `CC-BY-4.0` | +| `schemas/`, `sql/`, `context/`, `registry/`, `vectors/`, `fixtures/` | Creative Commons Zero 1.0 Universal | `CC0-1.0` | +| `tools/` | Apache License 2.0 | `Apache-2.0` | + +The legal texts are at , and . + +The formats are open so that anyone may implement them, in any product, without asking. + +All text in the fixtures is synthetic, written for them. +License fields inside fixtures describe fictional works, not the fixtures. +The keys in `fixtures/keys/` are public test keys and must never sign anything else. + +Copyright 2026 the Scientific Computing Studio. diff --git a/README.md b/README.md index d03fdf7..9e6d5b3 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,135 @@ -# varve-spec +# paperspec -The specifications of the Scientific Computing Studio's data formats: documents and their packages, anchors, receipts, rights, layers, exercises, datasets, digitizations, views, projects and bundles. -This is the repository the design calls `spec`, the baseline every other part implements. +**The data formats for storing a team's scientific papers once, correcting them once, addressing them down to the sentence, and keeping them.** -`spec` defines data, and data outlives code. -Every file any part writes is defined here, and a conforming file can be read without the part that wrote it. -Formats are named `scienting-/`, never after a product, so a product can be renamed without touching data. +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 documentation and every file of the specification are published at , and the repository is at . -## What is here +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. -| Path | Holds | -| --- | --- | -| [spec/](spec/README.md) | The normative chapters. Start with [spec/00-introduction.md](spec/00-introduction.md). | -| [schemas/](schemas/) | JSON Schemas (draft 2020-12) for every file and record. | -| [sql/](sql/) | Tables for SQLite, Dolt and PostgreSQL, and the SQLite bundle with full-text search. | -| [context/](context/) | The JSON-LD context that makes layers W3C Web Annotations. | -| [registry/](registry/) | Formats and media types, validation rule IDs, download-stamp rules and the default stage requirements. | -| [vectors/](vectors/README.md) | Test vectors for every computed value. | -| [fixtures/](fixtures/README.md) | Valid packages and records, invalid packages with the rule each breaks, and the test keys that signed them. | -| [tools/](tools/README.md) | The non-normative oracle that computed the vectors, the builder and the checker. | -| [DECISIONS.md](DECISIONS.md) | Where this text refines or departs from the design, and the decisions still open. | +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)). -## Check it - -Python 3.10 or later, with nothing installed: - -```sh -python3 tools/check.py +```text +cornell1995second-saqk#k3m9q2a@4f1a0c[12:57] +└────── document ────┘└ node ┘└ pin ┘└span┘ ``` -It validates every schema, record and package, refuses every invalid package for the stated rule, recomputes every vector, rebuilds the fixtures and vectors and compares them byte for byte, loads every package into SQLite and unloads it byte for byte, and lints the prose. -With `jsonschema` installed it also validates every record a second time with that library. -`make check` does the same and runs `markdownlint` when it is available. +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. +The document key's last four characters, `saqk`, are the start of a hash of the paper's DOI, so two papers that a citation key alone would name alike never share a key ([spec/02 §2.4](spec/02-model.md#24-work-and-document-keys)). -## Implement it +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. -An implementation conforms to the chapters and the vectors. -`scienting-core` (Python, standard library only) is the reference implementation of the shared rules, and `core-ts` the browser's; each runs this suite in its CI. -The oracle in `tools/` is not a library and is not meant to be imported: it exists so that no vector is typed by hand. +## Start here -## Status +| 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) | -Version 0.1.0. -The formats of milestone M1 are `candidate`; datasets, digitizations, views, projects, bundles and the draft formats are `provisional` until their milestones; see [registry/formats.json](registry/formats.json). +## What is in the repository + +| Folder | Holds | +| --- | --- | +| [spec/](spec/README.md) | The specification, in 24 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. | +| [deploy/](deploy/README.md) | How the website at is built and served. | + +## 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`, `load`, `validate` and `stress`. +`pixi run python tools/site.py` builds the website into `_site/` ([deploy/](deploy/README.md)). + +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-damb +``` + +## Format names + +Every format is named `scienting-/`, 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://paperspec.scient.ing/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 32 formats, 19 are `candidate` and 13 are `provisional`. +The `provisional` formats are project, bundle, dataset, digitization, view, snapshot, draft-ids, exercise, submission, grade, checklist, log-entry and checkpoint; 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, `` ([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 chapters and other prose are licensed CC BY 4.0. -Schemas, SQL, the JSON-LD context, the registries, the vectors and the fixtures are dedicated to the public domain under CC0 1.0, so anyone may implement the formats. -The tools are licensed Apache-2.0. +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). diff --git a/context/README.md b/context/README.md new file mode 100644 index 0000000..8ab07a7 --- /dev/null +++ b/context/README.md @@ -0,0 +1,129 @@ +# JSON-LD context + +Three readers use this page. +A newcomer, such as a student who has not met these formats, can read it from the top. +Each term is defined where it first appears, and the example comes from the fixtures. +An implementer who is writing a reader, writer, converter or checker will find the exact behavior, the defining chapter, the files that pin it, and the traps in "Using the context". +An expert who knows the neighboring standards will find the status of the formats and a short comparison in "Status and comparison". + +## What the context is + +Annotations are notes attached to a passage of a paper, such as a plain-language explanation of a term or a question for a study group. +Annotation layers store them as JSON, a text format for structured data, one annotation per line. +A shared standard, the [World Wide Web Consortium (W3C) Web Annotation Data Model](https://www.w3.org/TR/annotation-model/), says what an annotation contains: a body (the note), a target (what it is about) and a selector (how to find the passage inside the target). + +JSON-LD is JSON plus a rule that gives every field name a global meaning, written as an IRI (an identifier shaped like a web address). +The rule lives in a context, a file that maps short field names to IRIs. +Two tools that read the same context agree on what `target` or `status` means, even if they know nothing else about each other. + +`scienting-1.jsonld` is the context that makes every annotation layer valid JSON-LD, together with the W3C Web Annotation context. +The Web Annotation context supplies `Annotation`, `body`, `target` and `selector`. +This one supplies the terms the formats add. +Its address is `https://paperspec.scient.ing/context/scienting-1.jsonld`, which is this file as the project's website serves it, with the media type `application/ld+json` and a header that lets a browser fetch it from any page. +The terms it maps are listed at `https://paperspec.scient.ing/vocab`, and each term's IRI is a fragment of that page. +A processor that cannot reach the site loads the copy in this folder in its place. +Every layer and every annotation lists both contexts, Web Annotation first: + +```json +{"@context": ["http://www.w3.org/ns/anno.jsonld", "https://paperspec.scient.ing/context/scienting-1.jsonld"]} +``` + +The `scienting-` prefix is the formats' namespace, as in `scienting-layer/1` and `scienting-anchor/1`. +The repository's name, paperspec, is a separate matter. + +## An example from the fixtures + +[`fixtures/records/layer/annotations.jsonl`](../fixtures/records/layer/annotations.jsonl) holds nine annotations on the example paper `hale2026harmonic-damb`. +The first is a `gloss`, an explanation for a novice, of the phrase "bond force constant". +Shortened, it reads: + +```json +{"@context": ["http://www.w3.org/ns/anno.jsonld", "https://paperspec.scient.ing/context/scienting-1.jsonld"], + "type": "Annotation", "motivation": "describing", "status": "confirmed", + "body": {"type": "TextualBody", "kind": "gloss", "audience": "novice", + "value": "A *harmonic* term treats a bond like a spring: ..."}, + "target": {"type": "SpecificResource", + "source": "tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb", + "selector": [ + {"type": "AnchorSelector", + "anchor": {"format": "scienting-anchor/1", "node": "rr20tev", + "span": [111, 130], "quote": {"exact": "bond force constant", "...": "..."}, "...": "..."}}, + {"type": "TextQuoteSelector", "exact": "bond force constant", + "prefix": "rm{eq}})^2$$ where $K_r$ is the ", "suffix": " and $r_\\mathrm{eq}$ the equilib"}]}} +``` + +The Web Annotation context defines `type`, `motivation`, `body`, `target`, `source`, `selector`, `exact`, `prefix` and `suffix`. +This context defines `kind`, `status`, `audience`, `AnchorSelector` and `anchor`. + +## What it defines + +The file defines 23 terms. +Twenty-two map to IRIs under `https://paperspec.scient.ing/vocab#`: `format`, `kind`, `status`, `receipt`, `layer`, `audience`, `visibility`, `purpose`, `project`, `docs`, `pin`, `role`, `symbol`, `verdict`, `reason`, `reference`, `for`, `generator`, `exercise`, `anchor`, `rights_use` and the class `AnchorSelector`. +Three are renamed: `for` is `sct:questionFor`, `generator` is `sct:generatedBy`, and `rights_use` is `sct:rightsUse`. +The twenty-third, `total`, maps to `totalItems` in the ActivityStreams namespace. +Two terms carry a type rule. +A processor reads `layer` as an IRI, and it always reads `docs` as a set, so a one-element list stays a list. + +The file declares `anchor` and `exercise` as JSON literals (`"@type": "@json"`, a JSON-LD 1.1 feature, which is why the file sets `"@version": 1.1`). +A JSON-LD processor then keeps a `scienting-anchor/1` record intact instead of expanding it. +An anchor holds hashes (fixed-length fingerprints of text) and a `span`, a pair of character offsets whose order carries meaning. +Expansion would drop the anchor's unmapped field names ([JSON-LD 1.1 API, expansion step 13.3](https://www.w3.org/TR/json-ld11-api/#alg-expand-each-key-value)) and would give its arrays no order ([JSON-LD 1.1 §4.3](https://www.w3.org/TR/json-ld11/#sets-and-lists)). + +## The anchor selector and its fallback + +A selector says how to find a passage inside a source. +The standard selectors work from the passage's text or its position. +`TextQuoteSelector` holds the quoted text (`exact`, required) and optionally some text before and after it (`prefix`, `suffix`). +`TextPositionSelector` holds start and end offsets, which the model itself calls "very brittle with regards to changes to the resource" ([Web Annotation Data Model](https://www.w3.org/TR/annotation-model/)). + +`AnchorSelector` is the custom selector of these formats. +It carries a `scienting-anchor/1` record: the document key, the node ID, the node's `own_hash` and `node_hash` as they were when the anchor was made, an optional `span` in Unicode code points, a `quote`, and the document revision `rev` ([spec/06 §6.2](../spec/06-anchors.md#62-the-anchor)). +A reader can use the hashes to resolve the anchor against a corrected document and report one of five outcomes: `current`, `changed-below`, `moved`, `reattached` or `stale` ([spec/06 §6.5](../spec/06-anchors.md#65-resolution)). +A standard selector cannot do that. + +A tool that does not know `AnchorSelector` cannot use it. +An annotation's `selector` list puts the `AnchorSelector` first and, where the anchor has a quote, a standard `TextQuoteSelector` after it, for tools that do not know ours ([spec/18 §18.3](../spec/18-layers.md#183-the-annotation)). +The formats use no `TextPositionSelector` and no `FragmentSelector`. +Such a tool still reads the annotation's body and its `TextQuoteSelector`; the context matters only to tools that process the data as linked data. +That is the repository's statement; no Web Annotation client has been tested against these files. + +The fallback is not always there. +Three of the nine fixture annotations have only an `AnchorSelector` (the section-level question, the `generated` annotation on a figure and the exercise on a table), because the anchor points at a container and has no quote. + +## Using the context + +- Writer: Put both URLs (web addresses), in the order shown, in `@context` of `layer.json` and of every line of `annotations.jsonl`. [Chapter 18](../spec/18-layers.md) defines layers (§18.2), annotations (§18.3) and bodies (§18.4). +- Reader: Follow [chapter 6](../spec/06-anchors.md) to resolve an anchor. + The file `vectors/resolve.jsonl` resolves seventeen anchors against `fixtures/packages/hale2026harmonic-damb` and gives every outcome. +- JSON-LD processor: Use a JSON-LD 1.1 processor; the context relies on `@json` and `@version` 1.1. +- Checker: `schemas/annotation.schema.json` and `schemas/layer.schema.json` validate the files. `tools/check.py` also checks that each annotation's ID derives from its content and that the receipt at `fixtures/records/layer/receipt.json` covers each `confirmed` annotation. + +The traps: + +- No test vector pins the context, and nothing in `tools/` reads `scienting-1.jsonld`. + The schemas require only that `@context` be an array of at least two non-empty strings; they do not check the URLs. + A file with a wrong context can pass the checker and still expand wrongly. +- `@context` is part of an annotation's content hash (the hash covers everything except `status`, `receipt` and `modified`). + Rewriting or reordering the array changes the hash that a receipt covers. +- `format` is one term for two jobs: the layer's `format` (`scienting-layer/1`) and a text body's `format` (`text/markdown`). + The scienting context maps it to `sct:format`. + The Web Annotation context maps `format` to `dc:format` and protects none of its terms, and in an array of contexts the later definition wins ([JSON-LD 1.1 §4.1](https://www.w3.org/TR/json-ld11/#advanced-context-usage)), so listing this context second makes `format` mean `sct:format`. +- A consumer that does not use a field must still preserve it when it rewrites a file. + A tool that rewrites layers must not drop the scienting terms ([spec/00 §0.4](../spec/00-introduction.md)). +- The `TextQuoteSelector` repeats the anchor's plain quotation, and is left out when the quote is hashed (over 200 code points) or keyed ([spec/18 §18.3](../spec/18-layers.md#183-the-annotation)), so a public layer never shows text that a keyed anchor withholds. + +## Status and comparison + +The specification is version 0.1.0. +`scienting-layer/1`, `scienting-anchor/1` and `scienting-exercise/1` are `candidate` in [`registry/formats.json`](../registry/formats.json). +The specification defines `candidate` as "Complete, with vectors and fixtures, and ready to implement." +The context file is normative ([spec/00 §0.5](../spec/00-introduction.md)). + +The W3C Web Annotation Data Model is a 2017 W3C Recommendation and the general standard for annotating web resources, with existing clients that form an ecosystem these formats do not have ([Web Annotation Data Model](https://www.w3.org/TR/annotation-model/)). +Its standard selectors carry no content hash of the target text and define no outcomes such as `moved` or `stale`. +Its remedy for a changing resource is to record a state of the whole resource. +Hypothesis stores a quote selector with 32 characters of context and reattaches by fuzzy matching ([Hypothesis, fuzzy anchoring](https://web.hypothes.is/blog/fuzzy-anchoring/), 2013). +These formats store a hash pin and define the outcomes exactly. +The full comparison is in [docs/comparison.md](../docs/comparison.md). + +[Chapter 18](../spec/18-layers.md) defines layers and annotations. diff --git a/context/scienting-1.jsonld b/context/scienting-1.jsonld new file mode 100644 index 0000000..3f2cafa --- /dev/null +++ b/context/scienting-1.jsonld @@ -0,0 +1,42 @@ +{ + "@context": { + "@version": 1.1, + "sct": "https://paperspec.scient.ing/vocab#", + "format": "sct:format", + "kind": "sct:kind", + "status": "sct:status", + "receipt": "sct:receipt", + "layer": { + "@id": "sct:layer", + "@type": "@id" + }, + "audience": "sct:audience", + "visibility": "sct:visibility", + "purpose": "sct:purpose", + "project": "sct:project", + "docs": { + "@id": "sct:docs", + "@container": "@set" + }, + "pin": "sct:pin", + "role": "sct:role", + "symbol": "sct:symbol", + "verdict": "sct:verdict", + "reason": "sct:reason", + "reference": "sct:reference", + "for": "sct:questionFor", + "generator": "sct:generatedBy", + "exercise": { + "@id": "sct:exercise", + "@type": "@json" + }, + "anchor": { + "@id": "sct:anchor", + "@type": "@json" + }, + "AnchorSelector": "sct:AnchorSelector", + "rights_use": "sct:rightsUse", + "total": "as:totalItems", + "as": "https://www.w3.org/ns/activitystreams#" + } +} diff --git a/deploy/Caddyfile b/deploy/Caddyfile new file mode 100644 index 0000000..256fb33 --- /dev/null +++ b/deploy/Caddyfile @@ -0,0 +1,34 @@ +# Serves the paperspec website built by `python3 tools/site.py` (the `_site/` folder), copied to /srv/www/paperspec. +# The site mirrors the repository, so every schema is served at its $id and the JSON-LD context at the address +# layers name; this file sets the media types those addresses need and lets any page fetch them. +paperspec.scient.ing { + root * /srv/www/paperspec + encode zstd gzip + + # Every file may be fetched from any origin: JSON-LD processors and schema validators in browsers need it. + header Access-Control-Allow-Origin "*" + header X-Content-Type-Options "nosniff" + + # file_server keeps a Content-Type that is already set, so these take precedence over its defaults. + @jsonld path *.jsonld + header @jsonld Content-Type "application/ld+json" + @schema path /schemas/*.schema.json + header @schema Content-Type "application/schema+json" + @jsonl path *.jsonl + header @jsonl Content-Type "application/jsonl; charset=utf-8" + @package path *.sct.zip + header @package Content-Type "application/vnd.scienting.doc+zip" + @text path *.md *.py *.sql *.csv *.hex *.toml *.lock *.txt + header @text Content-Type "text/plain; charset=utf-8" + + # Pages and the search index change with each release; data files are cached briefly too, since the + # addresses stay the same across releases while their contents may not. + header Cache-Control "public, max-age=300" + + file_server + + handle_errors { + rewrite * /404.html + file_server + } +} diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..fe069ac --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,59 @@ +# Deploying the website + +This folder holds what it takes to serve the paperspec website at . +The site is static: `tools/site.py` builds it into `_site/`, and any web server can serve that folder. + +## What the site serves + +The site mirrors the repository, so a file at `schemas/anchor.schema.json` in the repository is served at `https://paperspec.scient.ing/schemas/anchor.schema.json`. +Three addresses that the formats themselves name depend on that: + +| Address | What is there | +| --- | --- | +| `https://paperspec.scient.ing/schemas/` | Each JSON Schema, at the address in its `$id`. | +| `https://paperspec.scient.ing/context/scienting-1.jsonld` | The JSON-LD context every layer and annotation lists. | +| `https://paperspec.scient.ing/vocab` | The vocabulary page, whose fragments are the IRIs of the context's terms. | + +Beside every Markdown file the builder writes a rendered page: `README.md` becomes its folder's `index.html`, and `X.md` becomes `X.html`. +A folder without a README gets a listing page, so every fixture and vector can be browsed. +The pages need no server-side code; search runs in the browser over a small index of headings, `search.json`. + +## Build it + +```sh +pixi run python tools/site.py # writes _site/ +pixi run python tools/site.py --out /tmp/paperspec-site +``` + +`pixi run check` builds the site into a temporary folder and checks that every Markdown file has a page, that every internal link and fragment resolves, that no Markdown is left unrendered, and that each schema's `$id`, the context's address and the vocabulary's IRIs are files of the site. + +To look at it locally, serve the folder with any static server, for example: + +```sh +pixi run python -m http.server --directory _site 8000 +``` + +## Serve it with Caddy + +[Caddyfile](Caddyfile) serves `/srv/www/paperspec` at `paperspec.scient.ing`. +It sets the media types the data needs (`application/ld+json` for the context, `application/schema+json` for schemas, `application/jsonl` for vectors and package files), allows every file to be fetched from any origin, and serves `404.html` for missing paths. +Add it to the server's Caddy configuration, for example with an `import` line, and reload Caddy. + +## Publish from CI + +The workflow `.gitea/workflows/site.yml` runs on every push to `main`. +It installs the environment from `pixi.lock`, runs `pixi run quick`, builds the site, and copies it with `rsync` to `/srv/www/paperspec`, the folder Caddy serves. +A failed check stops the publish, so the site never serves a release that does not pass its own checks. + +The copy is local: the `linux-base` runner starts each job in a container with the host's `/srv/www` mounted at the same path, so no key or secret is involved. +On a runner without that mount the workflow still builds and checks the site, and says that it did not publish. +`SITE_ROOT` and `SITE_SLUG` at the top of the workflow name the folder. + +Only changed files are copied, so every other file keeps its `Last-Modified` and `ETag` and caches stay valid across releases. +The environment in `.pixi/envs` is cached between runs under the hash of `pixi.lock`, so a fresh container installs it only when the lock file changes. + +## Distributing packages + +A zipped package is an ordinary file, and the site serves the fixtures as such. +For a team's own packages, the Gitea instance speaks the OCI distribution protocol, so packages can be pushed to and pulled from its package registry as OCI artifacts with ORAS, and signed there with cosign; the media type of the artifact is the package's, `application/vnd.scienting.doc+zip`. +Nothing in the formats depends on how packages travel. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..6869737 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,33 @@ +# Guides + +These guides explain paperspec to someone meeting it for the first time. +They serve three readers: a newcomer who has not seen the problem before, an implementer who will write a reader, writer, converter or checker, and an expert who knows the neighboring standards. +The [specification](../spec/README.md) says exactly what each format is. +The guides say what each format is for, with examples drawn from the fixtures. + +| Guide | For | +| --- | --- | +| [Overview](overview.md) | What paperspec is, who it serves, and how its parts fit together. | +| [Concepts](concepts.md) | The ideas behind the formats, one at a time, each with a real example. | +| [Walkthrough](walkthrough.md) | One paper, from a flawed first reading to a corrected, reviewed and signed document. | +| [Examples](examples.md) | Things to run: checking hashes by hand, reading a package with a few lines of Python, querying a database. | +| [Rationale](rationale.md) | Why the formats look the way they do, and the questions they leave open. | +| [Comparison](comparison.md) | How paperspec compares with JATS, TEI, W3C Web Annotation and other schemas. | +| [*FAQ*](faq.md) | Short answers to the questions people ask first. | +| [Glossary](glossary.md) | Every term, in a sentence. | + +## Reading orders + +**Newcomer.** Spend a first afternoon on the overview, then the walkthrough with the fixture open beside it, then the examples. +Read the concepts when a term in the walkthrough needs more than the glossary gives. + +**Implementer.** Start with the [specification's reading paths](../spec/README.md#reading-paths), which list the chapters to read for a reader, a converter, a store and a validator. +Chapters 0, 1, 3, 4 and 5 are needed for any of them. +Next, run the section "Test your implementation against a vector" in the examples. +Check your work against the [vectors](../vectors/README.md) and the [fixtures](../fixtures/README.md). +Chapter 22 of the specification defines conformance. + +**Expert.** Read the overview for scope and for what paperspec is not, then the comparison for how it differs from existing standards. +After that, read the rationale for the reason behind each rule and the questions it leaves open. +It ends with a list of limits. +Section 0.4 of the specification and [registry/formats.json](../registry/formats.json) give the status of each format: the version is 0.1.0, and each format is `candidate` or `provisional`. diff --git a/docs/comparison.md b/docs/comparison.md new file mode 100644 index 0000000..890f779 --- /dev/null +++ b/docs/comparison.md @@ -0,0 +1,481 @@ +# How paperspec compares with other schemas and standards + +A newcomer, such as a student who knows what a scientific paper and a citation are and has not met hashes, JSON-LD or annotation standards, can read each section's first paragraph and stop. +An implementer, who will write a reader, writer, converter or checker, gets the chapter that defines each behavior and the places where the formats differ from a neighbor in ways that cause bugs. +An expert, such as a researcher, standards author or reviewer who knows the neighboring standards, gets stated limits, the status of every format, and where the other standard is the better choice. + +The repository is at . +This page was checked against the repository, at the version given under "Limits and status". +Every statement about another standard links to the page it was read on, and those pages were read on 2026-10-12, so versions and dates are as of that day and may have moved. +Where the checked sources say nothing, this page says "not seen", "not specified" or "not in scope", and each phrase keeps one meaning: "not in scope" means the standard's own stated purpose excludes the feature, "not seen" means it was not found in the pages read (which is not proof it is absent), and "not specified" means the page read does not define it. + +A note on names. +The project is called paperspec. +Its formats are named `scienting-/`, for example `scienting-doc/1` and `scienting-anchor/1`. +That prefix is the formats' namespace, and the repository's name is a separate matter; formats are named after what they hold, never after a product or a repository. +The identifiers appear inside hashed data and test vectors, so they are not renamed. + +## The problem, and how to choose + +Suppose a research team keeps fifty papers it needs to understand completely. +A page number names a region of a PDF and cannot name a statement, and it changes between a preprint and the published version. +The team wants to point at one sentence or one table cell, such as `hale2026harmonic-damb#rr20tev@76e06b[111:130]` in the fixtures, and have that pointer keep working after someone fixes a misread digit elsewhere in the paper. +The pointer has four parts: + +- The document key, `hale2026harmonic-damb`. +- After `#`, the node ID, `rr20tev`. +- After `@`, the first six digits of the node's hash, `76e06b`, so the pointer names the sentence as it then read. +- In brackets, the code-point range of the words inside the sentence, `[111:130]`. +It also wants to know who compared a passage with the page image, and how far. +That is the problem paperspec's formats solve: they store a paper as a package of files in which every sentence, table cell and equation has a permanent address and every correction is recorded with its evidence. +Each level of checking is tied to the exact text it was checked against. + +Most of the standards below solve different problems, so this page compares by problem solved, not by rank. +The next table maps each job to the standard to start with and the section that compares it. + +| If your job is | Start with | Compare in | +| --- | --- | --- | +| Publishers and archives exchanging journal articles | JATS (Journal Article Tag Suite) | [JATS and JATS4R](#jats-niso-z3996-and-jats4r) | +| Encoding scholarly text, or extracting structure from PDFs | TEI, GROBID, Docling, MinerU, Marker | [TEI and GROBID](#tei-and-grobid), [PDF converters](#docling-mineru-and-marker) | +| Annotating a resource on the web | W3C Web Annotation | [Web Annotation](#w3c-web-annotation-selectors-and-hypothesis-style-anchoring) | +| Mining a corpus of millions of papers | S2ORC | [S2ORC and CORD-19](#s2orc-and-cord-19) | +| Publishing one claim as a citable object | Nanopublications, micropublications | [Claims](#nanopublications-and-micropublications) | +| Packaging data or files with metadata or fixity | Frictionless, RO-Crate, BagIt | [Packaging](#packaging-frictionless-data-package-ro-crate-and-bagit) | +| Identifying and registering works and datasets | schema.org, Crossref, DataCite | [Metadata](#metadata-schemaorg-crossref-and-datacite) | +| Generic provenance, canonical JSON (JavaScript Object Notation), Merkle trees | PROV-O, RFC 8785, RFC 6962, RFC 9162 | [Building blocks](#building-blocks-prov-o-rfc-8785-rfc-6962-and-rfc-9162) | +| Content-addressed storage | IPFS CIDs, SWHIDs | [Content addressing](#content-addressing-ipfs-cids-and-swhids) | +| Linking into a PDF, text or web page | RFC 8118, Media Fragments, RFC 5147, Text Fragments | [Fragment identifiers](#fragment-identifiers-and-pandoc) | +| Exchanging text-mining annotations, bibliographies, books | BioC, CSL-JSON, EPUB 3 | [BioC, CSL-JSON and EPUB 3](#bioc-csl-json-and-epub-3) | + +## What paperspec is, in the terms used below + +A few terms recur. +A hash is a fixed-length fingerprint computed from content, so any change to the content changes the hash; paperspec uses SHA-256, written as 64 lowercase hexadecimal digits ([spec/01 §1.3](../spec/01-conventions.md#13-hashes)). +Canonical JSON is a rule for writing JSON so that equal data always gives identical bytes, which is what makes a hash of JSON repeatable; paperspec uses the JSON Canonicalization Scheme of RFC 8785 ([spec/01 §1.1](../spec/01-conventions.md#11-canonical-json)). +A witness is one file of a paper, such as the publisher's PDF or a JATS XML file, identified by the SHA-256 of its bytes; a document is the text established from one or more witnesses ([spec/02 §2.1](../spec/02-model.md#21-four-objects)). +A package is a folder of canonical JSON files, or the same folder zipped as `.sct.zip`, with a manifest that lists every other file with its SHA-256 and size ([spec/12](../spec/12-package.md)). + +The design choices that matter for comparison: + +- **Node IDs:** A document is a tree of nodes (sections, paragraphs, sentences, cells, equations and so on, [spec/03](../spec/03-nodes.md)). + Each node has a 7-character ID, about 34.5 bits, valid as an HTML `id` and a URL fragment. + An ID is minted once from the document key, the node kind, the text hash and an occurrence count, then frozen: it is never recomputed, reassigned or reused. + It encodes no page, ordinal or kind. + A fresh conversion of the same input mints the same IDs ([spec/04 §4.2](../spec/04-identity.md#42-minting-node-ids)). +- **Five hashes per node:** `text_hash` covers the exact normalized text; `match_hash` is a strict projection that is the only value allowed to certify that two readings agree; `align_key` is a lossy projection that only proposes alignments; `own_hash` covers the node's own content; `node_hash` covers `{own, children}` as canonical JSON, so a change to one sentence changes the `node_hash` of each ancestor and nothing else ([spec/05 §5.1](../spec/05-hashes.md#51-the-five-values)). +- **Anchors:** An anchor stores a node ID, hashes, an optional span in Unicode code points and a quotation with up to 32 code points of context on each side. + Resolving it gives one of five results: `current`, `changed-below`, `moved`, `reattached` or `stale`, with a drift measure for `changed-below` ([spec/06](../spec/06-anchors.md)). +- **Corrections:** Corrections are appended, never edited. + Each carries evidence, an author and a reason, and a gate refuses a digit change without image evidence ([spec/11](../spec/11-corrections.md)). + In `fixtures/packages/hale2026harmonic-damb`, correction 1 replaces `3l0.0` with `310.0` because "OCR (optical character recognition) read the digit 1 as the letter l", with a crop of the page as evidence. +- **Fidelity and receipts:** Levels F0 (converted) to F3 (proofread). + F3 comes only from a signed receipt that lists the node at its current `node_hash`; a correction drops the node back ([spec/08](../spec/08-fidelity.md)). +- **Scale:** The formats are built for a team of roughly five to 20 people with a few dozen to a few hundred papers. + A 30-page paper is about 3,000 nodes, so 500 documents are about 1.5 million database rows ([spec/13 §13.2](../spec/13-database.md#132-tables)). + +## Summary table + +Each row summarizes the pages read for that standard. +Cells keep the wording of the verified source; the paperspec row is checked against the repository. +Maturity is left to the sections below, because a single word hides too much. + +| Standard | Sentence-level permanent IDs | Content hashes | Anchors or selectors | Correction history | Fidelity or signatures | Per-file rights | Numeric data anchors | Full-text structure | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **paperspec 0.1.0** | yes: 7-character IDs minted once, retired with a successor (spec/04) | yes: five SHA-256 values per node, plus keyed HMAC (hash-based message authentication code) forms (spec/05) | yes: ID, hash, quote, span, five outcomes with drift (spec/06) | yes: append-only, evidence-gated (spec/11) | yes: F0 to F3, signed receipts, spot-checks, error bounds (spec/08) | yes: per witness, with AI purpose and processor (spec/14) | yes: dataset values anchored to cells (spec/15; format `provisional`) | yes: sections to cells, equations, references (spec/03, 09) | +| [JATS standard page](https://www.niso.org/publications/z3996-2024-jats) (Z39.96-2024, v1.4) | not seen: no sentence element in the list shown | not seen | not in scope as an annotation model | not seen | not seen | partly: `permissions` and `license` elements exist | not seen | yes | +| [TEI P5](https://tei-c.org/guidelines/P5/) (v4.12.0) | partly: `` and author-assigned `xml:id` | not seen | partly: `xml:id` pointers, XPointer schemes | partly: ``, ``, `` | not seen | not seen | not seen | yes | +| [GROBID TEI output](https://grobid.readthedocs.io/en/latest/Grobid-service/) | partly: optional sentence elements; IDs not described | not seen | partly: optional PDF coordinates | no | no; reports F1 figures | not in scope | not seen | partly: header, references, citation contexts, full text | +| [W3C Web Annotation](https://www.w3.org/TR/annotation-model/) | not in scope | not in scope | yes: TextQuote, TextPosition, Fragment, XPath, Range selectors, refinement, States | not in scope | not in scope | not in scope | not in scope | not in scope | +| [Hypothesis anchoring](https://web.hypothes.is/blog/fuzzy-anchoring/) (2013 post) | no | no | yes: Range, Position, Quote selectors, 4 reattach strategies | not in scope | not in scope | not in scope | not in scope | not in scope | +| [DoclingDocument](https://raw.githubusercontent.com/docling-project/docling-core/main/docs/DoclingDocument.json) (schema 1.10.0) | no: positional `self_ref` | no per-item hash seen; `binary_hash` is file-level | partly: `prov` with page, bbox, `charspan` | not seen | not seen | not seen | partly: table cells with spans and header flags | yes | +| [MinerU](https://github.com/opendatalab/MinerU) | no: locators embed page and block numbers | not seen | partly: locators to a character offset within a block | not seen | not seen | not seen | not seen | yes | +| [Marker](https://github.com/datalab-to/marker) | no: block IDs such as `/page/10/Page/366` | not seen | not specified | not seen | not seen | not seen | not seen | yes: tree of blocks | +| [S2ORC / doc2json](https://github.com/allenai/s2orc-doc2json) | no: paragraph level | partly: `pdf_hash` (file-level; algorithm not verified) | partly: character spans for citations, refs, equations | no | no | partly: dataset-level ODC-By 1.0 | no | partly: paragraphs with section labels | +| [CORD-19](https://arxiv.org/abs/2004.10706) | not seen | not seen | not seen | not seen | not seen | not seen | not seen | partly: "structured full text" | +| [Nanopublications](https://nanopub.net/guidelines/working_draft/) | not in scope | partly: trusty URI hash identifies the unit | not in scope | partly: integrity key shows a unit changed | not seen | not seen | not in scope | not in scope | +| [Micropublications](https://jbiomedsem.biomedcentral.com/articles/10.1186/2041-1480-5-28) | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope (claim and argument model) | +| [Frictionless Data Package](https://datapackage.org/standard/data-package/) (v2) | not in scope | partly: optional resource `hash` (MD5 default) | not in scope | not in scope | not in scope | partly: `licenses` property | no | not in scope | +| [RO-Crate](https://www.researchobject.org/ro-crate/) (1.2 Rec) | not in scope | not seen (`contentSize` recommended) | not in scope | not seen | not seen | partly: schema.org license terms | not in scope | not in scope | +| [BagIt](https://www.rfc-editor.org/rfc/rfc8493) (RFC 8493) | not in scope | yes: per-file manifests, SHA-256 or SHA-512 | not in scope | not in scope | no: "not designed to be secure against active attacks" | not in scope | not in scope | not in scope | +| [schema.org ScholarlyArticle](https://schema.org/ScholarlyArticle) | no | partly: `sha256` on MediaObject | not in scope | partly: `correction` at work level | not in scope | partly: `license` (URL) at work level | not in scope | partly: `articleBody`, `hasPart`, `citation` | +| [Crossref deposit schema](https://www.crossref.org/documentation/schema-library/) (5.5.0) | not in scope | not seen | not in scope | partly: Crossmark, work level | not in scope | not verified | not in scope | not in scope: metadata only | +| [DataCite](https://schema.datacite.org/) (4.7) | not in scope | not seen | not in scope | not seen | not in scope | not seen | not in scope | not in scope: metadata only | +| [PROV-O Recommendation](https://www.w3.org/TR/prov-o/) | not in scope | not in scope | not in scope | partly: `wasInvalidatedBy`, `wasDerivedFrom` | not in scope | not in scope | not in scope | not in scope | +| [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) | not in scope | not in scope (canonical form only) | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope | +| [RFC 6962](https://www.rfc-editor.org/rfc/rfc6962) / [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162) | not in scope | yes: Merkle Tree Hash definition | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope | +| [IPFS content addressing page](https://docs.ipfs.tech/concepts/content-addressing/) | no: addresses blocks and files | yes: identity is the hash | not in scope | no: new content gives a new CID | no | not in scope | not in scope | not in scope | +| [SWHID core identifiers](https://www.swhid.org/specification/v1.2/5.Core_identifiers/) (ISO/IEC 18670:2025) | not in scope | yes: SHA-1 based intrinsic identifiers | not in scope here | not in scope | not in scope | not in scope | not in scope | not in scope | +| [RFC 8118](https://www.rfc-editor.org/rfc/rfc8118) (PDF) | no | no | partly: page, destination, region, first-word search | no | no | no | no | no | +| [Media Fragments](https://www.w3.org/TR/media-frags/) | no | no | partly: time and region; nothing on text | no | no | no | no | no | +| [RFC 5147](https://www.rfc-editor.org/rfc/rfc5147) (text/plain) | no | partly: `md5=` and `length=` checks | yes: `char=` and `line=` | no | no | no | no | no | +| [Text Fragments](https://wicg.github.io/scroll-to-text-fragment/) (WICG draft) | no | no | partly: exact-text match with optional prefix and suffix | no | no | no | no | no | +| [Pandoc AST](https://hackage.haskell.org/package/pandoc-types) (pandoc-types 1.23.1) | not verified | not verified | not verified | not in scope | not in scope | not in scope | not in scope | yes: document AST (details not verified) | +| [BioC](https://pmc.ncbi.nlm.nih.gov/articles/PMC3889917) | not seen | not seen | yes: document-level offset and length per annotation | not in scope | not in scope | not in scope | not in scope | partly: passages and optional sentences | +| [CSL-JSON markup page](https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html) | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope | not in scope: bibliographic items | +| [EPUB 3.3](https://www.w3.org/TR/epub-33/) | not seen | not seen | not seen (CFI not confirmed) | not seen | not seen | not seen | not seen | yes | + +## JATS (NISO Z39.96) and JATS4R + +*What it is.* +JATS, the Journal Tag Suite, is an XML vocabulary in which publishers and archives exchange journal articles. +It is ANSI/NISO Z39.96-2024, version 1.4, approved by ANSI on October 9, 2024 and published October 31, 2024, under continuous maintenance ([NISO page](https://www.niso.org/publications/z3996-2024-jats)). +Its tag sets are Journal Archiving and Interchange (most permissive), Journal Publishing (moderately prescriptive) and Article Authoring (most prescriptive), continuing NLM DTD work begun in 2002 ([jats.nlm.nih.gov](https://jats.nlm.nih.gov/)). +JATS4R is a NISO working group that publishes tagging recommendations and a validator ([JATS4R](https://jats4r.niso.org/)). + +*What it does well.* +It models journal-article structure and metadata: sections, paragraphs, table wrappers and cells, reference lists, related articles, footnotes, display formulas, supplementary material, permissions and licenses ([1.4 tag library](https://jats.nlm.nih.gov/archiving/tag-library/1.4/)). +Crossref's 5.4.0 deposit schema imports JATS ([Crossref](https://www.crossref.org/documentation/schema-library/metadata-deposit-schema-5-4-0/)), and a toolkit for S2ORC has a script for PMC JATS XML ([allenai/s2orc-doc2json](https://github.com/allenai/s2orc-doc2json)). + +*How paperspec differs.* +JATS has `` and `` elements; where they may be placed was not verified, so no per-file rights comparison is made. + +*Where JATS is the better choice.* +For publisher and archive exchange of journal content, and for the JATS4R recommendations on tagging consistency. +paperspec is not a publisher interchange format and does not replace JATS ([spec/02 §2.3](../spec/02-model.md#23-witnessesjson)). + +*Interoperation.* +JATS is an input. +`jats` is a witness kind, and the fixture `okafor2025solvent-acth` was established from a JATS file and a PDF that agree ([fixtures/README.md](../fixtures/README.md)). +The document's `meta` is one CSL-JSON item, not JATS front matter ([spec/02 §2.2](../spec/02-model.md#22-documentjson)). +The specification defines no JATS exporter. + +## TEI and GROBID + +*What they are.* +The TEI P5 Guidelines are the Text Encoding Initiative's reference documentation, maintained by the TEI Consortium; the release table shows version 4.12.0, released 2026-07-28 ([TEI P5](https://tei-c.org/guidelines/P5/)). +GROBID is a Java machine-learning library that converts PDFs and similar documents to structured data, with full encoding in TEI for results ([GROBID introduction](https://grobid.readthedocs.io/en/latest/Introduction/)). +It is Apache-2.0 licensed and can return PDF coordinates ([repository](https://github.com/kermitt2/grobid)). + +*What they do well.* +TEI has a sentence-like element `` ([TEI element s](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-s.html)). +Its ``, `` and `` markup preserves both readings of a corrected passage ([TEI element corr](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-corr.html)), and `` marks facsimile regions ([TEI element zone](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-zone.html)). +Pointers use `xml:id`, recommended "For durability in the presence of editing", plus XPointer schemes such as `xpath()`, `string-range()` and `match()` ([TEI pointers chapter](https://tei-c.org/release/doc/tei-p5-doc/en/html/SA.html)). +GROBID extracts header metadata, references, citation contexts and full text with coordinates, and reports, in its own documentation's documentation, an F1 of about 0.87 for references on a PubMed Central set and 0.76 to 0.91 for citation contexts; it describes itself as production ready ([introduction](https://grobid.readthedocs.io/en/latest/Introduction/)). +Its `segmentSentences` option splits paragraphs into sentence elements, and `teiCoordinates=s` adds a bounding box to each ([service documentation](https://grobid.readthedocs.io/en/latest/Grobid-service/)). + +*How paperspec differs.* +TEI's `xml:id` is author-assigned and durable by recommendation ([TEI pointers chapter](https://tei-c.org/release/doc/tei-p5-doc/en/html/SA.html)); paperspec IDs are minted by a rule and retired by recorded successor. +GROBID's output is an automatic reading with the accuracy figures above, not a corrected, reviewed text ([introduction](https://grobid.readthedocs.io/en/latest/Introduction/)). + +*Where they are the better choice.* +TEI for scholarly text encoding in general, and for apparatus-style correction markup inside a text. +GROBID as a PDF-to-structure converter for the reference and citation-context tasks it reports figures for. + +*Interoperation.* +TEI from GROBID could be one reading of a PDF. +paperspec has no `tei` witness kind, so that reading would be recorded as `xml` ([spec/02 §2.3](../spec/02-model.md#23-witnessesjson)). +The mechanism for comparing that reading with another is sentence alignment, which pairs sentences, keeps the first reading's IDs for paired sentences, and turns every disagreement into a suspect for review ([spec/05 §5.6](../spec/05-hashes.md#56-alignment)). +No TEI or GROBID mapping is defined in the repository. + +## W3C Web Annotation, selectors, and Hypothesis-style anchoring + +*What it is.* +The Web Annotation Data Model is a W3C Recommendation of 23 February 2017, edited by Robert Sanderson, Paolo Ciccarese and Benjamin Young ([model](https://www.w3.org/TR/annotation-model/)); the Web Annotation Vocabulary has the same date ([vocabulary](https://www.w3.org/TR/annotation-vocab/)). +Hypothesis is an annotation tool whose 2013 blog post describes its anchoring; current client behavior was not verified ([post](https://web.hypothes.is/blog/fuzzy-anchoring/)). + +*What it does well.* +An annotation has a body, a target and a motivation, and the vocabulary lists motivations such as commenting, describing, highlighting, linking and questioning ([vocabulary](https://www.w3.org/TR/annotation-vocab/)). +Targets are narrowed by selectors ([model](https://www.w3.org/TR/annotation-model/)): + +- `TextQuoteSelector`: `exact` required, `prefix` and `suffix` recommended. +- `TextPositionSelector`: `start` and `end`, which the model calls "very brittle with regards to changes to the resource". +- `FragmentSelector`, `XPathSelector` and `RangeSelector`, and refinement of one selector by another. +- States (`TimeState`, `HttpRequestState`), which pin a representation of the whole resource. + +Hypothesis stores a range selector (XPaths plus offsets), a position selector and a quote selector with 32 characters of context, and reattaches in four steps: range, position, context-first fuzzy match, then selector-only fuzzy match ([post](https://web.hypothes.is/blog/fuzzy-anchoring/)). +It identifies a PDF by an embedded fingerprint, which "persists across copies of the same document, but not across variants" ([Hypothesis help](https://web.hypothes.is/help/annotations-not-syncing-across-copies-of-a-pdf/)). + +*How paperspec differs.* +Hypothesis's post lists its own limits: it assumes the system can tell two formats are the same document, mapping text to the DOM (the browser's tree of page elements) is slow on long documents, and mappings update only when Hypothesis itself changes the DOM ([post](https://web.hypothes.is/blog/fuzzy-anchoring/)). +paperspec defines exact resolution outcomes and a hash pin where Hypothesis uses fuzzy matching. + +*Where they are the better choice.* +The Web Annotation model and vocabulary for annotation in general, existing Web Annotation tools, and Hypothesis as a working annotation service on web pages and PDFs. + +*Interoperation.* +A paperspec layer is a set of W3C Web Annotations whose target lists a custom `AnchorSelector` carrying a `scienting-anchor/1` record, optionally followed by a standard `TextQuoteSelector` "for tools that do not know ours" ([spec/18 §18.3](../spec/18-layers.md#183-the-annotation)). +The layers do not use `TextPositionSelector` or `FragmentSelector`. +The JSON-LD context (a file that maps the added terms to IRIs (internationalized web identifiers), so linked-data tools can read them) is at `https://paperspec.scient.ing/context/scienting-1.jsonld` ([context/README.md](../context/README.md)); whether that address resolves was not checked. +Whether a generic Web Annotation client displays an `AnchorSelector` was not verified. +Both Hypothesis and paperspec store a quote with 32 characters of prefix and suffix ([spec/06 §6.2](../spec/06-anchors.md#62-the-anchor)). + +## Docling, MinerU and Marker + +*What they are.* +Docling is an open-source document conversion toolkit, MIT-licensed (the paper is an arXiv preprint: [paper, arXiv:2501.17887](https://arxiv.org/abs/2501.17887)); `docling-core` defines its data types ([repository](https://github.com/docling-project/docling-core)), and DoclingDocument is "a unified document representation introduced with Docling v2" ([documentation](https://docling-project.github.io/docling/concepts/docling_document/)). +MinerU converts PDFs and Office documents to Markdown or JSON, states that it is not a RAG (retrieval-augmented generation) framework, and uses a custom license based on Apache 2.0 with additional conditions ([MinerU](https://github.com/opendatalab/MinerU)). +Marker converts documents to Markdown, JSON, chunks and HTML; its code is Apache 2.0 and its model weights carry a modified AI Pubs Open Rail-M license ([Marker](https://github.com/datalab-to/marker)). + +*What they do well.* +Docling's schema (version 1.10.0 on `main`) covers texts, pictures, tables, groups, furniture and pages; items carry a `self_ref` such as `#/texts/12`, `label`, `prov` (page, bounding box, `charspan`) and text; tables have cells with spans and header flags ([schema](https://raw.githubusercontent.com/docling-project/docling-core/main/docs/DoclingDocument.json)). +Docling uses AI models for layout analysis and table structure recognition and is reported integrated with LangChain, LlamaIndex and spaCy ([abstract](https://arxiv.org/abs/2501.17887)). +MinerU describes locators of the form `doc:{id}/tier:{tier}/page:{n}/block:{n}/char:{offset}` ([MinerU](https://github.com/opendatalab/MinerU)); Marker's JSON is a tree of blocks with an `id`, a `section_hierarchy` and `images` ([Marker](https://github.com/datalab-to/marker)). + +*How paperspec differs.* +The Docling `TextItem` field list has no per-item hash and its `label` enum has no sentence value, so items are block-grained ([schema](https://raw.githubusercontent.com/docling-project/docling-core/main/docs/DoclingDocument.json)). +Identifiers in all three are positional: `self_ref` indexes into lists, Marker's example IDs embed a page number, and MinerU's locators embed page and block numbers. +MinerU's guide says to preserve locators for citation. +It "does not explain what makes them stable or guarantee that they won't change across reparses" ([MinerU](https://github.com/opendatalab/MinerU)). +Docling's `charspan` is a span within an item on a page. +It is not a pinned, quote-verified anchor with resolution outcomes. + +*Where they are the better choice.* +For converting PDFs and other formats, layout analysis, table structure recognition, integrations, and one-shot structured output. +paperspec does not read PDFs; extracting lines from a PDF is outside its text ([spec/07 §7.1](../spec/07-geometry.md#71-page-fingerprints)). + +*Interoperation.* +These are converters, which paperspec treats as backends. +A backend declaration records the tool's code and weight licenses, and a stage may run only if they pass the gate ([spec/14 §14.4](../spec/14-rights.md#144-backends-and-profiles)); `provenance.json` records the backends and cached readings used ([spec/12 §12.4](../spec/12-package.md#124-provenance)). +Docling appears in the repository only as data: an illustrative declaration, version `illustrative`, in `fixtures/records/backend-docling.json` and `vectors/rights.jsonl`. +Their JSON output is not a named witness kind. +Reconciling their readings with others uses alignment and suspects ([spec/05 §5.6 and §5.7](../spec/05-hashes.md#56-alignment)). + +## S2ORC and CORD-19 + +*What they are.* +S2ORC, "The Semantic Scholar Open Research Corpus", is a corpus of 81.1 million English-language academic papers with structured full text for 8.1 million open-access papers, resolved bibliographic references and inline mentions of citations, figures and tables linked to paper records (Lo, Wang, Neumann, Kinney and Weld, ACL 2020, pp. 4969 to 4983, [ACL Anthology](https://aclanthology.org/2020.acl-main.447/)). +CORD-19, "The COVID-19 Open Research Dataset", was submitted April 22, 2020 as an arXiv preprint ([arXiv:2004.10706](https://arxiv.org/abs/2004.10706)). +S2ORC is now maintained by the Semantic Scholar API product team; the original files were refactored into datasets on the APIs, which need a key, and the original 2019 and 2020 releases "are no longer available for download" ([repository](https://github.com/allenai/s2orc)). + +*What they do well.* +Scale, and citation-mention linking across papers: the paper, an arXiv preprint, reports 380.5 million resolved citation links, 156.5 million of them tied to inline mentions ([arXiv:1911.02782](https://arxiv.org/pdf/1911.02782)). +The schema classes include `Paper`, with `pdf_hash`, `metadata`, `body_text`, `bib_entries` and `ref_entries`, and `Paragraph`, with `cite_spans`, `ref_spans` and `eq_spans` given as `start`, `end` and `text` ([s2orc.py](https://raw.githubusercontent.com/allenai/s2orc-doc2json/master/doc2json/s2orc.py)). +Sources are PDF via GROBID, PMC JATS XML and arXiv LaTeX ([doc2json](https://github.com/allenai/s2orc-doc2json)). + +*How paperspec differs.* +Table cells are not nodes ([s2orc.py](https://raw.githubusercontent.com/allenai/s2orc-doc2json/master/doc2json/s2orc.py)). +The paper states limitations, among them GROBID-derived inline-citation errors, linking that depends on titles, and LaTeX-derived metadata "worse than those extracted from PDF" ([arXiv:1911.02782](https://arxiv.org/pdf/1911.02782)). +The release formats "have changed over time" ([doc2json](https://github.com/allenai/s2orc-doc2json)). + +*Where they are the better choice.* +Corpus-scale text mining and citation-graph work across the literature, which paperspec explicitly does not target. + +*Interoperation.* +The purposes and scales differ. +S2ORC-style JSON could be a source of text readings. paperspec has no S2ORC witness kind. +The `same_as` list takes `doi:`, `arxiv:`, `isbn:`, `pmid:`, `pmcid:` and `url:` among its prefixes and has no Semantic Scholar identifier ([spec/02 §2.1](../spec/02-model.md#21-four-objects)). + +## Nanopublications and micropublications + +*What they are.* +A nanopublication is "a small knowledge graph snippet with metadata" in RDF ([nanopub.net](https://nanopub.net/)). +The guidelines describe four graphs (head, assertion, provenance, publication info), an identifier for each nanopublication, and trusty URIs as the recommended integrity mechanism ([guidelines](https://nanopub.net/guidelines/working_draft/)). +That page carries no version number, date or status. +Trusty URIs put cryptographic hash values in URIs so that resources can be verified and kept unchanged (an arXiv preprint: [Kuhn and Dumontier, arXiv:1401.5775](https://arxiv.org/abs/1401.5775)). +Micropublications are a semantic model for claims, evidence, arguments and annotations in biomedical communication ([Clark, Ciccarese and Goble, J Biomed Semantics 2014, 5:28](https://jbiomedsem.biomedcentral.com/articles/10.1186/2041-1480-5-28)). + +*What they do well.* +A claim-sized unit with machine-readable provenance and publication metadata, with an integrity check on the unit. +Micropublications add a claim, its supporting representations as a directed acyclic graph rooted at the claim, and challenges; the paper says they aim to present primary evidence while nanopublications "model only the indicated statement" ([paper](https://jbiomedsem.biomedcentral.com/articles/10.1186/2041-1480-5-28)). + +*How paperspec differs.* +These models do not store the paper's text. +The guidelines read do not describe pinning a passage, and they do not mention signatures; a Java library's README shows RSA public-key signing; the signature structure was not verified ([nanopub-java](https://github.com/Nanopublication/nanopub-java)). + +*Where they are the better choice.* +Publishing a claim as a citable, hash-verifiable, linked-data object, and representing support and challenge among claims. +paperspec does not define claim semantics; a statement true independently of one paper belongs outside this repository, and a statement about reading the paper belongs in a layer ([spec/18 §18.1](../spec/18-layers.md#181-one-rule-decides-what-is-a-claim-and-what-is-a-layer)). + +*Interoperation.* +A layer annotation can say that a span states, uses or disputes a claim kept elsewhere ([spec/18 §18.4](../spec/18-layers.md#184-bodies)). +A nanopublication's provenance could point at a paperspec address, since an address is a URL fragment (`…#node`, [spec/06 §6.1](../spec/06-anchors.md#61-addresses)); that is an inference, and no such mapping is defined in either project. + +## Packaging: Frictionless Data Package, RO-Crate and BagIt + +These three describe or protect a bundle of files. + +*Frictionless Data Package.* +It is "a simple container format for describing a coherent collection of data in a single package"; the descriptor `datapackage.json` requires `resources`, and version 2 is labeled current ([datapackage.org](https://datapackage.org/standard/data-package/); the v1 page shows 2007 to 2017, [specs.frictionlessdata.io](https://specs.frictionlessdata.io/data-package/)). +A resource's `hash` is MD5 by default, with other algorithms written as `algorithm:value` ([data resource](https://datapackage.org/standard/data-resource/)). +It describes tabular files and their schemas portably. +Not seen: hashing that covers descriptor and files in canonical form, per-value anchors to a source text, units and uncertainty. +It remains the right choice for the tabular container and its tooling, which paperspec adopts: a `scienting-dataset/1` is a Data Package plus units (strings a unit parser called Pint can read), uncertainty and an `origin`, with reported values anchored to the table cells or sentences that print them ([spec/15](../spec/15-datasets.md)). +The Data Package version paperspec uses is not stated in spec/15. +The dataset format is `provisional` ([registry/formats.json](../registry/formats.json)). + +*RO-Crate.* +It is "a community effort to establish a lightweight approach to packaging research data with their metadata", using schema.org annotations in JSON-LD ([RO-Crate](https://www.researchobject.org/ro-crate/)). +Version 1.2 is a Recommendation published 2025-06-04, and the site calls 1.3 the newest ([1.2](https://www.researchobject.org/ro-crate/specification/1.2/index.html)). +It describes a folder's contents in `ro-crate-metadata.json`, and file entities should include `contentSize` ([data entities](https://www.researchobject.org/ro-crate/specification/1.2/data-entities.html)). +Use it for general research-object description and discovery with schema.org vocabularies. +A paperspec package folder could be described by an RO-Crate. +No such mapping exists in either project. + +*BagIt.* +RFC 8493 defines a bag: `bagit.txt`, a `data/` payload of opaque octet streams, and at least one `manifest-.txt`; BagIt 1.0 tools must support SHA-256 and SHA-512 ([RFC 8493](https://www.rfc-editor.org/rfc/rfc8493)). +The RFC says it "is not designed to be secure against active attacks", and it has no signatures, content-level structure or payload semantics. +BagIt fits fixity and transfer of arbitrary payloads, archives and repositories. +paperspec's `MANIFEST.json` plays a similar fixity role, with a path, SHA-256 and size per file, and the hash of the manifest pins the package; the file layout differs ([spec/12 §12.3](../spec/12-package.md#123-the-manifest)). +A package could be a bag's payload, since payload files are opaque (an inference). + +## Metadata: schema.org, Crossref and DataCite + +*What they are.* +`ScholarlyArticle` is a schema.org type under Thing, CreativeWork and Article ([schema.org](https://schema.org/ScholarlyArticle)); release 30.1 is listed as 2026-09-16 ([releases](https://schema.org/docs/releases.html)). +Crossref's deposit schema is at 5.5.0, the version Crossref recommends ([schema library](https://www.crossref.org/documentation/schema-library/)). +DataCite Metadata Schema 4.7 was released 3 March 2026 and defines "core metadata properties chosen for an accurate and consistent identification of a resource" ([DataCite](https://schema.datacite.org/)). + +*What they do well.* +Bibliographic and identification metadata. +schema.org's `CreativeWork` has `text`, `citation`, `hasPart`, `version`, `license` and a `correction` property ([CreativeWork](https://schema.org/CreativeWork)), and `MediaObject` has `sha256` ([MediaObject](https://schema.org/MediaObject)). +Crossref's Crossmark lets publishers show whether an item was corrected, retracted or updated, including to readers holding an older download ([Crossmark](https://www.crossref.org/documentation/crossmark/)). + +*How paperspec differs.* +These are record-level. +A correction is flagged on the work, not on a sentence with evidence for each changed digit; the body has no node hashes; there are no fidelity levels or signed receipts; and rights are license-level information about the work, not per-file use grants with an AI purpose and processor. +None of the schema pages read describes body text, and the extent of Crossref's license and text-mining fields was not verified ([Crossref 5.4.0](https://www.crossref.org/documentation/schema-library/metadata-deposit-schema-5-4-0/)). + +*Where they are the better choice.* +Identifying and describing works and datasets with DOIs (digital object identifiers), discovery, registering corrections and retractions at the work level, and structured data on web pages. +paperspec is not a citation index and imports from Crossref, OpenAlex, PubMed Central and arXiv and never depends on them ([docs/overview.md](../docs/overview.md#what-it-is-not)). + +*Interoperation.* +The document's `meta` is a CSL-JSON item and `same_as` holds a DOI. +For open-access papers a producer sets `license` and a provisional rights basis from Crossref, and Crossref's license field is a named kind of evidence in a rights record ([spec/14 §14.1](../spec/14-rights.md#141-the-rights-record)). +No mapping from `meta` to Crossref, DataCite or schema.org is defined. + +## Building blocks: PROV-O, RFC 8785, RFC 6962 and RFC 9162 + +*PROV-O.* +It is a W3C Recommendation of 30 April 2013 that expresses the PROV Data Model in OWL2, with the classes Entity, Activity and Agent and properties such as `wasGeneratedBy`, `wasDerivedFrom` and `wasInvalidatedBy` ([PROV-O Recommendation](https://www.w3.org/TR/prov-o/)). +It is a general vocabulary and defines no node hashes, anchor resolution, corrections or receipts. +paperspec does not use it: provenance is a file, `provenance.json`, defined in the repository ([spec/12 §12.4](../spec/12-package.md#124-provenance)). +PROV-O is the better choice for linked-data provenance that other systems can query generically. +A mapping of stages and corrections to Activity and Entity is possible. +Nothing in either project defines one. + +*RFC 8785 (JSON Canonicalization Scheme).* +Published June 2020 as an Informational RFC, it sorts object properties recursively in UTF-16 code unit order, keeps array order, writes numbers by ECMAScript rules, uses no whitespace, outputs UTF-8, and does not normalize Unicode strings ([RFC 8785](https://www.rfc-editor.org/rfc/rfc8785)). +It is a building block that defines no document model, and paperspec uses it: every hash of JSON is over RFC 8785 output. +paperspec adds rules on top: a decimal that carries meaning is a string, so `310.0` and `1.5260` keep their printed digits, and a document with a lone surrogate, `NaN` or an infinity has no canonical form and is invalid ([spec/01 §1.1 and §1.2](../spec/01-conventions.md#11-canonical-json)). + +*RFC 6962 and RFC 9162 (Merkle trees).* +A Merkle tree hashes items pairwise up to one root, so one short value commits to all of them. +RFC 6962 (Certificate Transparency, June 2013, Experimental) is obsolete; RFC 9162 (Certificate Transparency Version 2.0, published December 9, 2021, Experimental) "obsoletes RFC 6962" ([RFC 6962](https://www.rfc-editor.org/rfc/rfc6962), [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162)). +Both give the same Merkle Tree Hash: a leaf is `HASH(0x00 || d)`, an interior node is `HASH(0x01 || left || right)`, and a list splits at the largest power of two smaller than n. +paperspec's receipts use this construction with SHA-256 and cite RFC 6962 ([spec/08 §8.5](../spec/08-fidelity.md#85-merkle-roots)). +They differ in one rule: a receipt with no items is invalid in paperspec, while the RFC defines the hash of an empty list. +The citation is to the obsolete RFC; the tree it defines is the one RFC 9162 also defines. +paperspec's `node_hash` is not this construction (see "Limits and status" below). + +## Content addressing: IPFS CIDs and SWHIDs + +*IPFS CID.* +A content identifier is derived from the content's hash, and "any difference in the content will produce a different CID"; a CID holds the hash and the codec, with sha-256 as the default hash ([IPFS docs](https://docs.ipfs.tech/concepts/content-addressing/)). +It gives verifiable, location-independent identity to immutable data. +A CID covers the root block of a DAG (directed acyclic graph), "not a direct hash of the file's bytes", so chunk size, layout, codec, version and hash all change the CID for the same file. +Identity and content are the same thing, so an edit makes a new identifier; the page describes no ID that survives edits, no sentence granularity, corrections or fidelity. +Keep using CIDs for storage and distribution of immutable blobs. +paperspec's asset store names files by SHA-256, not CID ([spec/12 §12.6](../spec/12-package.md#126-assets)). + +*Software Heritage SWHID.* +ISO/IEC 18670:2025 specifies the SoftWare Hash IDentifier, version 1.2, published April 2025 ([ISO catalog page](https://www.iso.org/standard/89985.html); [swhid.org](https://www.swhid.org/specification/v1.2/)). +Core identifiers have the form `swh:1::` for contents, directories, revisions, releases and snapshots, each SHA-1 over a typed header and a serialized form, and "intrinsic": computed from the object's content and relevant metadata, not its location ([core identifiers](https://www.swhid.org/specification/v1.2/5.Core_identifiers/)). +The qualified-identifier clause was not read. +Keep using SWHIDs for persistent, content-derived identification and archiving of source code. + +*The contrast.* +A CID or SWHID is a function of content at all times. +A paperspec node ID is derived from content once, at minting, and then frozen; the content hashes live separately in `node_hash`, so the pair of ID and hash tells whether the text has changed ([spec/04 §4.2 and §4.3](../spec/04-identity.md#42-minting-node-ids), [spec/05 §5.1](../spec/05-hashes.md#51-the-five-values)). +paperspec's hashes are SHA-256 ([spec/01 §1.3](../spec/01-conventions.md#13-hashes)). +The cost of the choice: because the ID is minted from the text hash, two independent conversions that read a sentence differently by one character mint different IDs for it. + +## Fragment identifiers and Pandoc + +A fragment identifier is the part of a URL after `#` that says where to look inside the resource. + +- **PDF fragments (RFC 8118):** Informational, March 2017. + Parameters include `page`, `nameddest`, `structelem`, `zoom`, `viewrect`, `highlight` and `search`; none selects text by character offset, `search` "selects the first matching word in the document", and `highlight` takes rectangle coordinates ([RFC 8118](https://www.rfc-editor.org/rfc/rfc8118)). + Keep using it to open a PDF at a page, destination or region. paperspec's `locations.jsonl` stores per-node page boxes as `[x0, y0, x1, y1]` in PDF points against page fingerprints ([spec/07 §7.4](../spec/07-geometry.md#74-locationsjsonl)), so a tool could build an RFC 8118 link; the repository does not define that. +- **Media Fragments URI 1.0:** A W3C Recommendation of 25 September 2012 that defines time (`t=`) and spatial (`xywh=`) fragments for audio, video and images, and says nothing about text ([Media Fragments](https://www.w3.org/TR/media-frags/)). + It is a weak fit for text passages. +- **RFC 5147 (text/plain):** A Proposed Standard of April 2008 with `char=` and `line=` positions counted from zero and integrity checks `length=` and `md5=`, "to detect whether the resource has changed" ([RFC 5147](https://www.rfc-editor.org/rfc/rfc5147)). + It is the closest older precedent to a position-plus-integrity address; it uses MD5 only and applies to plain text, not to paper structure. +- **Text Fragments:** A WICG Draft Community Group Report, not a W3C standard; the version read is dated 13 December 2023 and may not be the latest. + The syntax is `#:~:text=[prefix-,]start[,end][,-suffix]`, it matches the first exact occurrence, and it is restricted to top-level navigations ([WICG draft report](https://wicg.github.io/scroll-to-text-fragment/)). +- **DOM and XPath approaches:** W3C `XPathSelector` and `RangeSelector` ([model](https://www.w3.org/TR/annotation-model/)), TEI's `xpath()` scheme ([TEI pointers chapter](https://tei-c.org/release/doc/tei-p5-doc/en/html/SA.html)) and Hypothesis's first strategy, which "fails if the XPath expressions can no longer be applied" ([post](https://web.hypothes.is/blog/fuzzy-anchoring/)). + Path addressing breaks when structure changes; paperspec's display paths are never stored or cited ([spec/04 §4.3](../spec/04-identity.md#43-permanence-retirement-and-aliases)). +- **Pandoc:** The pandoc-types library defines the `Pandoc` document type with modules for building, walking and JSON conversion; the latest on Hackage is 1.23.1, uploaded 2023-08-06 ([Hackage](https://hackage.haskell.org/package/pandoc-types)). + Its Block and Inline types and its treatment of identifiers were not verified. `latex` is a paperspec witness kind ([spec/02 §2.3](../spec/02-model.md#23-witnessesjson)); Pandoc is not mentioned in the repository. + +On the web, a paperspec node ID is the URL fragment, so `…#k3m9q2a` lands on the sentence ([spec/06 §6.1](../spec/06-anchors.md#61-addresses)). +This is a plain HTML fragment, not a registered fragment scheme; the chapters define no fragment syntax for the package media type. + +## BioC, CSL-JSON and EPUB 3 + +*BioC.* +BioC is a simple extensible XML format for sharing text documents and annotations between natural-language-processing and text-mining tools, with code to read and write it ([BioC paper](https://pmc.ncbi.nlm.nih.gov/articles/PMC3889917); [bioc.sourceforge.net](https://bioc.sourceforge.net/)). +Its model has collection, source, document, passage, optional sentence, annotation and relation, with `infon` key-value pairs, and an annotation's location is an offset and length relative to the whole document. +Its authors state that it "targets tool developers and not end users" and "focuses on text data rather than other media". +Keep using it to exchange text-mining annotations among biomedical natural-language-processing (NLP) tools. +Offsets would need conversion, since paperspec counts Unicode code points ([spec/01 §1.5](../spec/01-conventions.md#15-character-offsets)) and the length unit in BioC was taken from a page summary and not confirmed. +No BioC mapping is defined. + +*CSL-JSON.* +It is a JSON format for bibliographic items consumed by Citation Style Language (CSL) processors; items require `id` and `type`, `author` is an array of name objects, and `issued` uses `date-parts` or `raw` ([markup page of the CSL-JSON documentation](https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html)). +Its schema is described as "not yet fully normative" ([CSL schema](https://github.com/citation-style-language/schema)). +Keep using it for bibliographic interchange with citation processors and reference managers. +paperspec embeds CSL-JSON as the document's `meta` and as the optional parsed `csl` of each reference ([spec/02 §2.2](../spec/02-model.md#22-documentjson), [spec/10](../spec/10-references.md)). + +*EPUB 3.* +EPUB 3.3 is a W3C Recommendation, "a distribution and interchange format for digital publications and documents": a ZIP container with a package document listing a manifest and a spine, and XHTML or SVG content documents ([EPUB 3.3](https://www.w3.org/TR/epub-33/)). +It suits reflowable publications. +Keep using it as a reading and distribution format. +`epub` is a paperspec witness kind ([spec/02 §2.3](../spec/02-model.md#23-witnessesjson)), and the zip package rules (UTF-8 names, one top-level folder, no symlinks) are the package's own ([spec/12 §12.2](../spec/12-package.md#122-paths)). + +## Limits and status + +*Status.* +The specification is version 0.1.0. +`registry/formats.json` lists 32 formats: 19 are `candidate` (complete, with vectors and fixtures, ready to implement) and 13 are `provisional` (complete; expected to change as implementations gain experience): project, bundle, dataset, digitization, view, snapshot, draft-ids, exercise, submission, grade, checklist, log-entry and checkpoint ([spec/00 §0.4](../spec/00-introduction.md#04-status)). +The repository holds 24 chapters, 42 JSON Schemas, 25 vector files, five valid fixture packages, one of them also zipped, and 31 invalid ones, each naming the rule it breaks, and a reference checker, `tools/check.py`. +Licenses: prose CC BY 4.0; schemas, SQL, the JSON-LD context, registries, vectors and fixtures CC0 1.0; tools Apache-2.0 ([README.md](../README.md#licenses)). + +*No adoption claim.* +The repository names no outside adopter and no independent implementation, and this page claims none. + +*Scope of this comparison.* + +The pages read cover no ORKG, DocBook, PubAnnotation, OpenAlex or PMC OA XML material, so those are not compared. +A statement that no single comparator combines paperspec's features describes the pages read and surveys no other systems. + +*What paperspec does not do.* + +- It is not a publisher interchange format; it ingests JATS and other formats as witnesses and does not replace them ([spec/02 §2.3](../spec/02-model.md#23-witnessesjson)). +- It is not a search engine, a citation index, a recommendation feed or a chat-with-a-PDF tool ([docs/overview.md](../docs/overview.md#what-it-is-not)). + Search is a per-bundle SQLite FTS5 index (the bundle format is `provisional`), which is the extent of its search ([spec/13 §13.5](../spec/13-database.md#135-the-bundle)). +- It does not define claim semantics ([spec/18 §18.1](../spec/18-layers.md#181-one-rule-decides-what-is-a-claim-and-what-is-a-layer)). +- It does not model glyph-level PDF layout beyond per-node boxes; extracting lines from a PDF is outside its text ([spec/07 §7.1](../spec/07-geometry.md#71-page-fingerprints)). +- It compares complex math by source only; comparing canonical MathML is a possible later addition ([spec/05 §5.3](../spec/05-hashes.md#53-the-strict-projection), [docs/rationale.md](../docs/rationale.md#questions-the-formats-leave-open)). +- It is built for hundreds of documents, not hundreds of millions, and it does not fix what a converter reads wrongly; it records the error and makes it checkable. + +*Where the repository's guides are looser than the specification.* +The specification governs. +These are the places where the guides and the specification differ, and this page uses the corrected statements. + +1. **Reconversion:** `README.md` says an address "survives reconversion with a better tool". + The specification says a fresh conversion of the same input mints the same IDs ([spec/04 §4.2](../spec/04-identity.md#42-minting-node-ids)). + With a different converter, sentences the alignment pairs keep their IDs and every difference becomes a suspect ([spec/05 §5.6](../spec/05-hashes.md#56-alignment); [docs/faq.md](../docs/faq.md)). + IDs survive a better converter only for paired sentences. +2. **"Merkle":** The guides and spec/05 §5.1 call the root `node_hash` a Merkle root. + A `node_hash` is a hash of the canonical JSON of `{"own": own_hash, "children": [...]}`. + Only receipts follow the RFC 6962 construction ([spec/08 §8.5](../spec/08-fidelity.md#85-merkle-roots)). + The two constructions are not the same. +3. **"Opaque" IDs:** Calling IDs meaningless or random is loose. + An ID is minted by the rule given above, so it is neither meaningless nor random. +4. **Five hashes everywhere:** `docs/overview.md` lists the things that get "a permanent ID and five content hashes" without naming them. + Table columns and figure-text items have IDs, are not nodes, and carry no five hashes ([spec/04 §4.2](../spec/04-identity.md#42-minting-node-ids), [spec/09 §9.1](../spec/09-figures-tables-equations.md#91-figures-and-panels)). +5. **Dataset digits:** spec/15 says values keep their printed digits, and in JSON they are strings. + The fixture descriptor `fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/datapackage.json` types the field `k_r` as `number`. + How Frictionless tools treat that was not verified, so take care when comparing with Frictionless Table Schema. +6. **Package tree:** `docs/concepts.md` omits `suspects.jsonl` from its package tree, and [spec/12 §12.1](../spec/12-package.md#121-files) lists it. +7. **RFC 6962 is obsolete:** spec/08 §8.5 cites it; RFC 9162 obsoletes it (see above). +8. **Status:** The guides describe the formats as one set. + Of the 32 formats, 13 are `provisional`, including `scienting-dataset/1`, which the datasets paragraphs in `docs/concepts.md` present without that qualifier. + +*The distinguishing combination, and what it costs.* +paperspec puts in one package permanent sentence- and cell-level IDs, five hashes per node, anchors with explicit resolution outcomes and drift, append-only evidence-gated corrections, signed fidelity receipts with spot-check bounds, per-witness rights with AI-use axes, and value-to-cell anchors. +Individual pieces have precedents in the comparators: TEI correction markup, Web Annotation selectors, RFC 5147 integrity checks, RFC 6962 Merkle trees, BagIt manifests and Frictionless packaging. +No single comparator in the pages read combines them. +The price is weight: five hashes per node, a gate on corrections, signed records and a custom selector type. +The design target is a team's few dozen to few hundred papers; the weight is out of proportion for publisher exchange or corpus-scale mining. diff --git a/docs/concepts.md b/docs/concepts.md new file mode 100644 index 0000000..95491ea --- /dev/null +++ b/docs/concepts.md @@ -0,0 +1,448 @@ +# Concepts + +Each section introduces one idea, shows it in the example paper `hale2026harmonic-damb` (a synthetic chemistry paper in [fixtures/packages/](../fixtures/packages/)), and links to the chapter that defines it exactly. + +This page is written for three readers. +A newcomer, such as a student who knows what a paper and a citation are and is new to hashes, JSON and annotation standards, gets each term defined where it first appears, with the reason before the rule. +An implementer, who will write a reader, writer, converter or checker, gets the chapter that defines each behavior, the test vector file that pins it, and the traps. +An expert, such as a researcher, standards author or reviewer who knows the neighboring standards, gets the limits and the status of each format, and a short note wherever a close relative exists elsewhere. + +The longer comparisons are on [the comparison page](comparison.md). +For a gentler start, read the [overview](overview.md) first; for the exact rules, use the [specification](../spec/README.md). + +Two facts apply to everything below. +The specification is at version 0.1.0. +It defines 32 formats, 19 of them `candidate` and 13 `provisional`, as [registry/formats.json](../registry/formats.json) lists. +The provisional ones are the project, bundle, dataset, digitization, view, snapshot, draft-ids, exercise, submission, grade, checklist, log-entry and checkpoint formats; the sections below say so where they describe them. + +Format identifiers such as `scienting-anchor/1` and `scienting-correction/1` begin with `scienting-`, which is the formats' namespace. +The repository's name, paperspec, is a separate matter, and the formats are named after what they hold. +The repository is at . + +## Hashes and canonical JSON + +Two tools appear in almost every section. + +A *hash* is a short fingerprint computed from data. +This specification uses SHA-256, which turns any sequence of bytes into 64 hexadecimal digits. +The same bytes always give the same digits, and changing one character gives unrelated digits. +Comparing two fingerprints tells you whether two texts are identical without comparing the texts. +The fingerprint cannot be turned back into the text. +The SHA-256 of the cell text `310.0` in the example begins `b478fd…`. +Hashes are written as 64 lowercase hexadecimal digits; six digits are used only for display and for pins in addresses ([chapter 1.3](../spec/01-conventions.md#13-hashes)). + +*JSON* is a plain-text format for structured data: objects with named members, lists, strings and numbers. +The same JSON data can be written in many ways (members in any order, spaces anywhere), and a hash of each way would differ. **Canonical JSON** fixes one way, so that every writer produces the same bytes and a hash of the data means the same thing everywhere. + +The specification uses the JSON Canonicalization Scheme of [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785): no whitespace, members sorted by name, and numbers written as ECMAScript writes them. +Strings are not Unicode-normalized, and a document containing a lone surrogate, `NaN` or an infinity has no canonical form and is invalid. +The specification adds one rule on top: a decimal that carries meaning is written as a string, so that `310.0` and `1.5260` keep their printed digits. +Every hash of a JSON value here is a hash of its canonical JSON encoded as UTF-8. + +RFC 8785 is a building block and says nothing about what to put in the JSON. This specification adopts it for the canonical form and adds the decimal and invalid-value rules above ([chapter 1.1](../spec/01-conventions.md#11-canonical-json), [1.2](../spec/01-conventions.md#12-numbers), [1.9](../spec/01-conventions.md#19-files)). + +Pinned by [vectors/canonical-json.jsonl](../vectors/canonical-json.jsonl). +A trap for implementers: the vectors parse every number as an IEEE 754 double, and sort member names as UTF-16 code units, not as bytes. + +## Works, versions, witnesses and documents + +Work, version, witness and document are easy to confuse, so the formats keep them apart. + +| Object | In the example | +| --- | --- | +| A work is the paper across all its versions. | Hale and Osei's paper on harmonic bond parameters, `doi:10.5555/example.hale.2026`. | +| A version is one expression of it: a preprint, the version of record, an erratum, the Supporting Information. | The version of record. | +| A witness is one file of a version, identified by its SHA-256. | The publisher's PDF, witness `qptsanv`. | +| A document is the text established for one version, from one or more witnesses. | `hale2026harmonic-damb`. | + +A document's key is its work's key, with a suffix for anything other than the version of record: `hale2026harmonic-damb.si` would be its Supporting Information. +A witness can be a PDF, a JATS file, a LaTeX archive, an HTML page, an EPUB, a Typst project, other XML, an image, or another file; these are the values of its `kind`. +See [chapter 2](../spec/02-model.md). + +## Keys + +A work key is a work's permanent name, built so that a reader can say it and so that it never collides. +It is a Scholar-style citation key (first author, year, first title word), a hyphen, and four characters of a hash of the work's identity, which is its DOI when it has one: + +```text +hale2026harmonic-damb +``` + +Two works that a citation key alone would name alike, a preprint and its published version, say, get different hashes. +A key is minted once, when the work enters a store, and never recomputed, so a corrected title changes nothing anyone has cited; if two works share four characters, the later one gets six. +A document key adds a suffix for a version other than the version of record: `hale2026harmonic-damb.si` would be the paper's Supporting Information. +See [spec/02 §2.4](../spec/02-model.md#24-work-and-document-keys); `keys.jsonl` pins the cases. + +## A document is a tree of nodes + +Every part of the text is a node: the document, its sections, headings, paragraphs and sentences, figures and their panels and captions, tables with their rows and cells, equations, footnotes and references. +The example has 75 nodes, 45 of them leaves (nodes that hold text themselves). +This outline shows its two sections and the equation, figure and table in them: + +```text +p36k8t6 1 Introduction +tkxsmts equation (1) +d400rz3 2 Methods +v7cx6qs figure Figure 1 +hj4s7pb table Table 1 +``` + +`nodes.jsonl` holds one node per line, in document order: the root first, then each node before its children. +Each line has the node's kind, parent, position among its siblings, content and hashes. +A sentence's content is a list of *runs*: plain text, styled text, inline math, citations, cross-references, footnote marks, links, and display equations the sentence runs through. +This is one table cell, shortened: + +```json +{"id":"c20cna6","kind":"cell","parent":"g8d2pjb","ord":1, + "attrs":{"column":"…","role":"data","rowspan":1,"colspan":1}, + "content":[{"kind":"text","text":"310.0"}], + "fidelity":"F1","text_hash":"…","match_hash":"…","align_key":"…","own_hash":"…","node_hash":"21f13b…"} +``` + +Page breaks, running heads and columns are not nodes; they are geometry ([chapter 7](../spec/07-geometry.md)). +See [chapter 3](../spec/03-nodes.md). + +Close relatives: [JATS 1.4](https://www.niso.org/publications/z3996-2024-jats) is an XML format in which publishers and archives exchange journal content, and TEI is a set of guidelines for encoding scholarly text. +Each is the better choice for its own job, and the paperspec formats do not replace them; a JATS file can be one witness of a document. +The element list in the [JATS 1.4 archiving tag library](https://jats.nlm.nih.gov/archiving/tag-library/1.4/) shows sections, paragraphs, table wrappers and cells and has no sentence element, while [TEI has an `` element](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-s.html). +Here the sentence is the unit that gets an ID and hashes. +See [the comparison page](comparison.md). + +## IDs are names, not positions + +`c20cna6` says nothing about where the cell is. +That is deliberate. +An ID that encoded a page or an ordinal would change when a better converter ordered blocks differently, and one that encoded a kind would change when a paragraph turned out to be a caption. +So an ID encodes no page, ordinal or kind. +It is seven characters, the first a letter, so it is valid as an HTML `id`, a CSS selector and a URL fragment. + +An ID is minted once, from a hash of the document key, the node's kind, the hash of its text and an occurrence count (the number of earlier nodes with the same kind and text, so that repeated sentences get different IDs). +Then it is frozen: it is never recomputed, reassigned or reused. +A fresh conversion of the same input mints the same IDs. +A different converter is not guaranteed to, because two readings that differ by one character would mint different IDs for that sentence. + +A second reading is aligned with the document sentence by sentence. +Sentences the alignment pairs keep the document's IDs, and every difference becomes a suspect, a recorded doubtful reading that a person resolves ([chapter 5.6](../spec/05-hashes.md#56-alignment) and [5.7](../spec/05-hashes.md#57-suspects)). + +One ID is retired and points at its successor when two nodes merge; an artifact's ID is retired with no successor when the artifact is deleted. +Legacy IDs, such as a block ID from an earlier numbering scheme, live on as aliases: in the example, `b-p01-text-003` still leads to sentence `hca6dc5`. +Both the retirements and the aliases are recorded in `ids.jsonl`. + +Not every addressable thing is a node. +The columns of a table and the text items found inside a figure panel get IDs by the same rule and carry no node hashes, so they do not have the five hashes described below. +In the example, Table 1's second column has the ID `wdtrcqt`, and the axis label "r (Å)" in Figure 1's first panel has the ID `rtxzjj9`. + +Pinned by [vectors/ids.jsonl](../vectors/ids.jsonl). +See [chapter 4](../spec/04-identity.md). + +Close relative: in TEI, `xml:id` is assigned by the author, and the Guidelines recommend it ["For durability in the presence of editing"](https://tei-c.org/release/doc/tei-p5-doc/en/html/SA.html); JATS has an [`id` attribute](https://jats.nlm.nih.gov/archiving/tag-library/1.4/attribute/id.html). +TEI's recommendation gives no rule for minting an ID from content or for retiring one with a successor. +For a text a person edits by hand, an author-assigned `xml:id` is the simpler tool. +See [the comparison page](comparison.md). + +## Addresses + +An address names a node, and optionally pins it to a state and narrows it to a span: + +| Address | Names | +| --- | --- | +| `hale2026harmonic-damb#hca6dc5` | The sentence about water, whatever it says now. | +| `hale2026harmonic-damb#hca6dc5@cd6cdb` | That sentence as it read when its `node_hash` began `cd6cdb`. | +| `hale2026harmonic-damb#hca6dc5@cd6cdb[29:44]` | Code points 29 to 44 of it in that state: "first test case". | +| `smithlab/hale2026harmonic-damb#hca6dc5` | The same sentence in the `smithlab` store. | + +The offsets count Unicode code points in the node's plain projection, which is its text as stored with math written between dollar signs. +The dollar signs count, which is why the span starts at 29: the sentence reads `Water, H$_2$O, served as the first test case, …`. + +On the web the ID is the fragment, so a link to `…/smithlab/hale2026harmonic-damb#hca6dc5` lands on the sentence. +Pinned by [vectors/addresses.jsonl](../vectors/addresses.jsonl). +See [chapter 6](../spec/06-anchors.md#61-addresses). + +## Five hashes, five jobs + +Every node carries five content values. +Table columns and figure-text items, from the previous section, do not. + +| Value | Covers | Answers | +| --- | --- | --- | +| `text_hash` | The text exactly, normalized. | Is this the same quotation, character for character? | +| `match_hash` | The text with notation folded to one form. | Do two witnesses really agree? | +| `align_key` | The text folded loosely. | Is this probably the same sentence? | +| `own_hash` | The node's own content, without its children. | Has this section itself changed, as opposed to something inside it? | +| `node_hash` | The node and everything below it. | Has anything here changed at all? | + +"Normalized" means Unicode normalization form C, runs of whitespace collapsed to one space, and leading and trailing space removed ([chapter 1.4](../spec/01-conventions.md#14-text-normalization-for-hashing)). `own_hash` is a hash of the canonical JSON of the node's own content, such as its runs or its label. `node_hash` is a hash of the canonical JSON of `{"own": own_hash, "children": [each child's node_hash, in order]}`. + +Each `node_hash` covers its children's, so a correction to one sentence changes that sentence's values and the `node_hash` of each ancestor, and nothing else. +This design is the idea of a Merkle tree, a tree in which each hash covers the hashes below it. +It is not the RFC 6962 construction that receipts use (see Receipts and spot-checks). + +The middle two exist because one hash cannot do both of their jobs. +Chemistry writes the same thing many ways, and every one of these sentences has the same `match_hash`: + +| As stored | Strict projection | +| --- | --- | +| `The solvent is $H_2O$.` | `The solvent is H_{2}O.` | +| `The solvent is H$_2$O.` | `The solvent is H_{2}O.` | +| `The solvent is H` and a subscript `2`, then `O.` | `The solvent is H_{2}O.` | +| `The solvent is H₂O.` | `The solvent is H_{2}O.` | +| `The solvent is $H_2 O$.` in Typst | `The solvent is H_{2}O.` | + +(The vectors also include a sixth spelling, `$\mathrm{H}_{2}\mathrm{O}$`, with the same `match_hash`.) + +OCR often drops a superscript, and "103" must never be certified as agreeing with 10³. So "A rate of 103 per second." and "A rate of 10³ per second." share an `align_key`, which proposes that they are the same sentence, while their `match_hash` values differ, which raises a suspect of kind `number` for a person to resolve. +The same care keeps "The energy" followed by citation 3 from matching the text "The energy3". + +The cost is that notation too complex to fold, such as a fraction, is compared by its source text alone, so two spellings of one complex formula do not match ([chapter 5.3](../spec/05-hashes.md#53-the-strict-projection)). + +Pinned by [vectors/projections.jsonl](../vectors/projections.jsonl), [vectors/projection-groups.jsonl](../vectors/projection-groups.jsonl) and [vectors/hashes.jsonl](../vectors/hashes.jsonl). +See [chapter 5](../spec/05-hashes.md). + +## Corrections + +A document is never edited in place. +Every fix is a correction: an operation with its evidence, its author and a reason, appended to `corrections.jsonl`. + +```json +{"format":"scienting-correction/1","index":1,"op":"replace","target":"c20cna6", + "find":"3l0.0","replace":"310.0", + "evidence":[{"kind":"crop","sha256":"9b6fe6…"}],"author":{"key":"ana"}, + "reason":"OCR read the digit 1 as the letter l.","at":"2026-10-02T10:00:00Z", + "before":"2fd1e9…","after":"21f13b…","touched":["c20cna6"]} +``` + +A document's history is its first reading plus its corrections, and its revision is the index of the last one. +The operations are `replace`, `insert`, `delete`, `split`, `merge`, `move`, `reclassify`, `relabel` and `set`. +Evidence is a crop (an image of the page region), a witness, a source file by SHA-256, or a named person. + +A gate refuses any correction that would change a digit without a crop of the page as evidence, or that would let a digit change anywhere it did not declare. +The same gate also refuses an `insert` without a crop and a `find` that does not occur exactly once. +Digits are the characters of Unicode category Nd. + +Pinned by [vectors/corrections.jsonl](../vectors/corrections.jsonl), which applies each operation and each refusal to a small document. +See [chapter 11](../spec/11-corrections.md). + +## Anchors + +Corrections change nodes and their hashes, so a note that points at a node has to survive them. +An anchor is how anything points into a document: a quotation that must match the paper word for word, an annotation, a dataset value, a draft's citation. +It is a pinned address with enough context to find its text again after the document changes: + +```json +{"format":"scienting-anchor/1","store":"smithlab","doc":"hale2026harmonic-damb","node":"hca6dc5","kind":"sentence", + "own_hash":"d5b2eb…","node_hash":"cd6cdb…","span":[29,44], + "quote":{"exact":"first test case","prefix":"Water, H$_2$O, served as the ","suffix":", with a bending band near 1595 "}, + "rev":12} +``` + +`rev` is the document's revision when the anchor was made. +It counts corrections, not clock time, because anchors are made on different machines and clocks disagree. +The `prefix` and `suffix` are up to 32 code points of context on each side of the quote. + +An anchor resolves one of five ways when the document changes. +Resolution first follows the ID table (aliases and successors), then looks for the quote, using the prefix and suffix to choose among repeats, then judges by the kind of node: + +| Result | Means | In the example | +| --- | --- | --- | +| `current` | Nothing it points at has changed. | A note on the water sentence. | +| `changed-below` | A container is unchanged in itself while something inside it changed; a drift figure says how much. | A note on Table 1 after rows were replaced and added. | +| `moved` | Its node was merged into another that still holds the quote. | A note on "least squares" in half of a sentence that was split at a line break, then rejoined. | +| `reattached` | Its node changed and the quote is still there exactly once, so it is re-pinned. | A note on "treated as zero" in a sentence whose superscript was fixed. | +| `stale` | It can no longer be trusted; a person must re-anchor it. | A note on the cell that read "3l0.0" before it was corrected to "310.0". | + +Drift is the share of the leaves below a container that corrections have touched since the anchor's revision; the default threshold for "high" is one quarter ([chapter 6.6](../spec/06-anchors.md#66-drift)). +Pinned by [vectors/resolve.jsonl](../vectors/resolve.jsonl), which resolves 17 anchors against the example. +See [chapter 6](../spec/06-anchors.md); the [walkthrough](walkthrough.md#5-what-happened-to-the-notes) shows all five. + +Close relative: the W3C Web Annotation Data Model defines selectors, including a [`TextQuoteSelector`](https://www.w3.org/TR/annotation-model/) (exact text with optional prefix and suffix) and a `TextPositionSelector` that the same document calls very brittle when the resource changes. +Its remedy for change is a state that pins a representation of the whole resource. +An anchor adds a node ID, two hash pins and the five defined outcomes. +The [Hypothesis anchoring approach](https://web.hypothes.is/blog/fuzzy-anchoring/) also stores a quote with 32 characters of context, and reattaches by fuzzy matching where this specification defines exact outcomes. +For annotation in general, the W3C model and its existing clients are the better choice; the Layers section below uses it directly. +See [the comparison page](comparison.md). + +## Fidelity + +Every leaf has a level that says how far its text was checked. + +| Level | Means | +| --- | --- | +| F0 converted | One reading, not corroborated. | +| F1 resolved | Every doubt about it was answered against the page image. | +| F2 corroborated | An independent witness agrees exactly, or the text was born digital. | +| F3 proofread | A named person compared it with the page and signed for its current text. | + +A level counts only at the node's current hash, so a correction drops a proofread sentence back until someone signs for it again. +The pipeline records F0, F1 or F2; F3 comes only from a valid receipt. +The example reports 27 leaves at F3, 13 at F2, 4 at F1 and 1 at F0, which is its 45 leaves. +See [chapter 8](../spec/08-fidelity.md). + +## Receipts and spot-checks + +Nobody signs three thousand nodes one at a time (a 30-page paper has about that many). +A reviewer signs a **receipt** instead: one signature over a Merkle root of everything reviewed in a sitting, with the evidence looked at. +A Merkle root is the single hash at the top of a tree of hashes, so one signature commits to every item below it. +In the example, the reviewer `ana` signs one receipt for 23 nodes: the cells of Table 1's three data rows and its four column headers, the equation and the sentences around it. + +Receipts use an RFC 6962 style tree over the reviewed nodes ([chapter 8.5](../spec/08-fidelity.md#85-merkle-roots)). +RFC 6962 has since been replaced by [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162), which gives the same tree definition. +One difference: this specification makes a receipt with no items invalid, while the RFC defines a hash for an empty list. + +Signing once per sitting invites rubber-stamping, so a second reviewer spot-checks a sample. +The sample is chosen by the checker's Ed25519 signature over the receipt, which neither reviewer can steer and anyone can recompute. +By default the sample is 5% of the nodes with a minimum of 10, so for the 23-node receipt it is 10 nodes. + +The record states a bound on each reviewer's error rate across samples: zero errors in 10 sampled nodes bounds the rate below 26%, and zero errors in 300 bounds it below 1%. These are one-sided upper confidence bounds at 95% confidence (Clopper-Pearson); with no errors the bound is about 3 divided by the sample size. + +A spot-check that finds an error suspends the receipt; a revocation withdraws it. +Either way the nodes fall back to the level they had without it. +Pinned by [vectors/merkle.jsonl](../vectors/merkle.jsonl), [vectors/spotcheck.jsonl](../vectors/spotcheck.jsonl) and [vectors/bounds.jsonl](../vectors/bounds.jsonl). +See [chapter 8](../spec/08-fidelity.md#83-receipts). + +## Page fingerprints + +Several publishers stamp each download with the institution and time, so two teammates' copies of one paper rarely share a SHA-256. +Each page also has a fingerprint: a hash of its size, its text with the stamp lines removed, and its images. + +Two downloads of the same page stamped "Downloaded via UNIVERSITY OF EXAMPLE on October 11, 2026" and "Downloaded via EXAMPLE PHARMA INC on March 2, 2027" share the fingerprint `6272e6f3…`; change one digit of the text and it becomes `b545d285…`. +Geometry and digitizations point at fingerprints, so a re-download keeps every box and every value read off a plot. + +The limit is in the stamp rules. +A missed stamp splits one edition into two, and an over-broad rule hides a real difference. +Pinned by [vectors/fingerprints.jsonl](../vectors/fingerprints.jsonl). +See [chapter 7](../spec/07-geometry.md). + +## Keeping text private + +A team may annotate a paper it may not share. +A **checks-only** package keeps every ID, label, page and box, and withholds the text. +It also keys every hash, because a plain hash of a short text such as "310.0" is recovered by hashing guesses. +A keyed hash (an HMAC) needs a secret key to compute, so guessing does not work without the key. + +Values are plain SHA-256 inside the team. +Exported to another of the team's machines, they are HMACs under the team's key. +In a public layer, or in an export outside the team, the key is derived from the paper's page fingerprints (see the previous section), so only someone holding the paper can check them. +Where the values go chooses the key, not whether the text is withheld. +[fixtures/packages/hale2026harmonic-damb.checks-only](../fixtures/packages/hale2026harmonic-damb.checks-only) is the example paper exported to another of the team's machines, so it uses the team key. + +A checks-only package also has no corrections, suspects or datasets. +Pinned by [vectors/keyed.jsonl](../vectors/keyed.jsonl). +See [chapter 5.8](../spec/05-hashes.md#58-keyed-hashes). + +## Rights + +What a team may do with a paper depends on how it holds the paper. +Every witness carries a rights record: the license as stated, the basis (an open license, a subscription, a collective license, the team's own work), and which uses that allows, including AI uses by purpose and by where the processing runs. +Every processing stage declares what it needs and runs only when the rights allow it. +A use that is not recorded counts as unknown, and unknown counts as no. + +The example PDF is held on a subscription that allows text mining and internal AI use on the team's own machines. +Conversion by a local model is allowed. +Conversion by an outside service is refused for lacking `ai/internal/outside`. +Model review in the team's cloud is refused for lacking `ai/internal/tenancy?` (the question mark means unknown) until a project owner signs a policy that settles it. +A policy can settle an unknown use and cannot override an explicit yes or no. +The refusal for `ai/internal/outside`, which the record sets to false, stands. + +The record also has an end date, after which every use is false. +Nothing here is legal advice. +Pinned by [vectors/rights.jsonl](../vectors/rights.jsonl). +See [chapter 14](../spec/14-rights.md). + +## Layers and annotations + +Everything people and models add is an annotation, grouped in layers. +The example layer is "Smith lab reading of Hale and Osei", for a student audience, visible to the team. + +Annotations are W3C Web Annotations whose selector is an anchor. +A custom `AnchorSelector` carries the anchor, followed by a standard `TextQuoteSelector` as a fallback for readers that do not know the first; there is no `TextPositionSelector` or `FragmentSelector`. +This gloss, shortened, explains a phrase for a first-year student: + +```json +{"type":"Annotation","motivation":"describing","status":"confirmed", + "body":{"type":"TextualBody","kind":"gloss","audience":"novice", + "value":"A *harmonic* term treats a bond like a spring: the energy grows with the square of the stretch."}, + "target":{"type":"SpecificResource","source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb", + "selector":[{"type":"AnchorSelector","anchor":{"node":"rr20tev","span":[111,130],"…":"…"}}, + {"type":"TextQuoteSelector","exact":"bond force constant"}]}} +``` + +One rule decides what is a claim and what is a layer. +A statement true independently of the paper is a claim, which is checked and leveled. +A statement about reading the paper belongs in a layer, where it is attributed and signed and not checked. +Claims are not defined in this repository. + +Model-written text is always a `generated` annotation, never source, and a model's annotation stays `proposed` until a person confirms it. +Whether a generic Web Annotation client displays an `AnchorSelector` has not been tested; the fallback exists so that it can still use the quote. +Layers are `candidate`. +Pinned by the layer records in `fixtures/records/layer/`. +See [chapter 18](../spec/18-layers.md). + +## Exercises + +Every sentence and cell has an address, so the answer to "find the evidence" is an address, and an address can be graded. +An exercise asks a student to find the cell giving the Set A bond constant for CT–CT. A student who points at `c20cna6` scores 1 of 1 with "That is the cell."; one who points at the Set B cell scores 0 with "Look in Table 1, row CT–CT." + +Students submit under pseudonyms, and a key whose anchors have gone stale is never used to grade. +Pinned by [vectors/grading.jsonl](../vectors/grading.jsonl). +The exercise, submission and grade formats are `provisional`: no course has used them yet, and the first that does will shape them. +See [chapter 19](../spec/19-exercises.md). + +## Datasets, digitizations and views + +Numbers live in prose, in tables and inside figures; all three should end up as data a team can plot and cite. +The dataset, digitization and view formats are all `provisional`: complete, and expected to change as implementations gain experience. + +A dataset is a Frictionless Data Package with units, uncertainty, and an origin for each resource or row. +The example's Table 1 becomes a CSV whose every value is anchored to the cell that prints it, digits exactly as printed: + +```text +key,bond,set,k_r,r_eq +ct-ct-a,CT–CT,A,310.0,1.526 +ct-ct-b,CT–CT,B,305.2,1.5260 +``` + +A digitization records how values were read off a plot (axes, calibration, series, uncertainty) and counts only once a person confirms it against an overlay. +A view is a Vega-Lite specification that names its data by dataset ID and hash. +See chapters [15](../spec/15-datasets.md), [16](../spec/16-digitization.md) and [17](../spec/17-views.md). + +Close relative: a [Frictionless Data Package](https://datapackage.org/standard/data-package/) is "a simple container format for describing a coherent collection of data in a single package". +The dataset format adopts it and adds units, uncertainty, origin and per-value anchors. +The spec does not state which Data Package version it uses. +See [the comparison page](comparison.md). + +## Packages, databases and bundles + +A document travels as a package: a folder of canonical JSON files, or the same folder zipped. + +```text +hale2026harmonic-damb/ + MANIFEST.json every other file, with its SHA-256; its own hash pins the package + document.json the work, version, metadata, policy, root hash and fidelity + nodes.jsonl one node per line, in reading order + witnesses.json each witness and its rights + pages.jsonl each page and its fingerprint + locations.jsonl where each node is on each page + references.jsonl parsed references + corrections.jsonl every correction, in order + receipts.jsonl receipts and revocations + ids.jsonl retired IDs and legacy aliases + suspects.jsonl suspects not yet resolved + roster.json the keys that signed + provenance.json tools, versions and where each stage ran + assets/ images, by SHA-256 + datasets/ datasets reported from the document + derived/ MathML and other renderings, rebuildable +``` + +Only `MANIFEST.json`, `document.json`, `nodes.jsonl`, `witnesses.json` and `provenance.json` are required, and an optional file with no records is left out; the example package omits `suspects.jsonl`. +Every line is canonical JSON, so a corrected sentence is a one-line diff, and every file has exactly one valid byte sequence. +This specification defines `provenance.json`, which records the tools and versions used and, for each stage, the processor where it ran. + +The same data loads into tables that run on SQLite, Dolt and PostgreSQL, and unloads back to the same bytes. +A bundle is one SQLite file with every table and a full-text index, which a reader or a server can query offline. +The bundle and project formats are `provisional`; the package format is `candidate`. +See chapters [12](../spec/12-package.md) and [13](../spec/13-database.md). + +Close relatives: [BagIt](https://www.rfc-editor.org/rfc/rfc8493) (RFC 8493) also packages files with a manifest of checksums, and is the better choice for transferring arbitrary payloads to archives; `MANIFEST.json` also lists files with checksums, in a different layout. [RO-Crate](https://www.researchobject.org/ro-crate/) describes a folder's contents with schema.org terms in JSON-LD and suits general research-object description; neither it nor BagIt defines addressing of sentences or cells. +For provenance, [W3C PROV-O](https://www.w3.org/TR/prov-o/) is a general W3C vocabulary (entities, activities, agents) that other systems can query generically; this specification does not use it, and no mapping between it and `provenance.json` is defined. +See [the comparison page](comparison.md). diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..91cc8bf --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,249 @@ +# Examples + +Things to run, each with the output it gives. +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, . +With [pixi](https://pixi.sh), `pixi run ` sets up the environment first. +Every command also works without pixi, with Python 3.14 and two packages, `jsonschema` and `cryptography` installed 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, 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 `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 + +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 +``` + +```text +175bfc8867816a9761fd5bb9ffc956df6d9e7f203870961a5485fc1912cb663a - +``` + +The same value is in the package, in the `nodes.jsonl` of `hale2026harmonic-damb`: + +```sh +grep -o '"id":"v3063qv".*' fixtures/packages/hale2026harmonic-damb/nodes.jsonl | grep -o '"text_hash":"[0-9a-f]*"' +``` + +```text +"text_hash":"175bfc8867816a9761fd5bb9ffc956df6d9e7f203870961a5485fc1912cb663a" +``` + +## Check a package's manifest + +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/okafor2025solvent-acth +sha256sum nodes.jsonl +grep -o '"path":"nodes.jsonl","sha256":"[0-9a-f]*"' MANIFEST.json +``` + +```text +09c9b99eed97987e51dd0f85461ad9ad8768a0769ba7facfb7e0879d742660a3 nodes.jsonl +"path":"nodes.jsonl","sha256":"09c9b99eed97987e51dd0f85461ad9ad8768a0769ba7facfb7e0879d742660a3" +``` + +## Read a package with nothing but a JSON parser + +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 + +pkg = sys.argv[1] +nodes = [json.loads(line) for line in open(pkg + "/nodes.jsonl", encoding="utf-8")] +by_id = {n["id"]: n for n in nodes} +children = {} +for n in nodes: + children.setdefault(n["parent"], []).append(n) + + +def text(n): + """The plain projection of a node with runs.""" + out = [] + for r in n["content"]: + if r["kind"] == "math": + out.append("$" + r["source"] + "$") + elif r["kind"] == "equation": + out.append("$$" + by_id[r["node"]]["content"]["source"] + "$$") + else: + out.append(r["text"]) + return "".join(out) + + +for n in nodes: + if n["kind"] == "section": + heading = children[n["id"]][0] + print(n["id"], n.get("label", ""), " ".join(text(s) for s in children[heading["id"]])) + elif n["kind"] in ("figure", "table", "equation"): + print(n["id"], " ", n["kind"], n.get("label", "")) +``` + +```sh +python3 outline.py fixtures/packages/hale2026harmonic-damb +``` + +```text +p36k8t6 1 Introduction +tkxsmts equation (1) +d400rz3 2 Methods +v7cx6qs figure Figure 1 +hj4s7pb 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-damb#hca6dc5[29:44]` names code points 29 to 44 of sentence `hca6dc5`. +With `text()` from the script above: + +```python +print(text(by_id["hca6dc5"])[29:44]) +``` + +```text +first test case +``` + +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-damb fixtures/packages/okafor2025solvent-acth fixtures/packages/writer2027fixed-ynr7.v3 +``` + +Without pixi, run `python3 tools/load.py` with the same arguments. + +```text +hale2026harmonic-damb: 75 nodes +okafor2025solvent-acth: 15 nodes +writer2027fixed-ynr7.v3: 15 nodes +``` + +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, and this repository has not yet run them on Dolt or PostgreSQL. +Here are four queries, in Python's `sqlite3` so that nothing else is needed. + +```python +import json, sqlite3 + +db = sqlite3.connect("lab.db") + +# Sentences the converter left below F2. Receipts can raise them; see below. +for row in db.execute("SELECT id, fidelity FROM nodes WHERE doc_key = 'hale2026harmonic-damb' " + "AND kind = 'sentence' AND fidelity IN ('F0', 'F1') ORDER BY seq"): + print(row) + +# Every sentence that cites reference 2: the citation graph is sentence-level. +for row in db.execute("SELECT c.sentence FROM citations c JOIN refs r " + "ON r.doc_key = c.doc_key AND r.node = c.ref_node " + "WHERE c.doc_key = 'hale2026harmonic-damb' AND r.label = '2'"): + print(row) + +# Who signed what. +for row in db.execute("SELECT r.signer, r.scope, COUNT(*) FROM receipts r " + "JOIN receipt_nodes rn ON rn.receipt = r.id GROUP BY r.id ORDER BY r.made_at"): + print(row) + +# Table 1's body, row by row. +rows = db.execute("SELECT r.id FROM nodes r JOIN nodes b ON b.doc_key = r.doc_key AND b.id = r.parent " + "WHERE r.doc_key = 'hale2026harmonic-damb' AND r.kind = 'row' AND b.kind = 'table-body' " + "ORDER BY r.seq").fetchall() +for (row,) in rows: + cells = db.execute("SELECT content FROM nodes WHERE doc_key = 'hale2026harmonic-damb' AND parent = ? ORDER BY ord", + (row,)).fetchall() + print(" | ".join("".join(r.get("text", "") for r in json.loads(c)) for (c,) in cells)) +``` + +```text +('ec5jc93', 'F1') +('a4jrz2t', 'F0') +('xjns57z', 'F0') +('hca6dc5',) +('ana', 'targeted:lode', 3) +('ana', 'targeted:lode', 23) +('ana', 'section:p36k8t6', 2) +('cara', 'page:2', 3) +('ana', 'targeted:captions', 3) +('ben', 'qa:y2zw8ctg5s8dp', 10) +('ben', 'qa:gx2s84z9jf9xv', 3) +Bond parameters +CT–CT | 310.0 | 1.526 | 305.2 | 1.5260 +CT–HC | 340.0 | 1.090 | 338.7 | 1.0900 +OW–HW | 553.0 | 0.9572 | 548.1 | 0.9570 +``` + +The first query reads the level the converter recorded, not the final one. +A receipt is a signed record that a reviewer checked certain nodes against the page. +Receipts by `ana` raise `ec5jc93` and `a4jrz2t` to F3; `xjns57z` 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. + +## 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: + +```python +import json + +for line in open("vectors/projections.jsonl", encoding="utf-8"): + case = json.loads(line) + runs = case["runs"] + # assert my_plain(runs) == case["plain"] + # assert my_strict(runs) == case["strict"] + # assert my_lossy(runs) == case["lossy"] + # assert my_sha256(case["strict"]) == case["match_hash"] + print(case["id"], case["strict"]) +``` + +[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 +sed -i 's/1718 cm/1719 cm/' fixtures/packages/okafor2025solvent-acth/nodes.jsonl +pixi run quick +``` + +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/okafor2025solvent-acth/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. diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000..05331bc --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,131 @@ +# FAQ + +This page answers questions about paperspec, a set of file formats that give every sentence and table cell of a scientific paper a permanent address. +Newcomers, implementers of a reader, writer, converter or checker, and experts who know JATS (Journal Article Tag Suite), TEI (Text Encoding Initiative) or W3C Web Annotations can all use it. +Each answer gives the plain statement first, then the precise one, then the chapter that defines it. +The repository is , and the formats are at version 0.1.0. + +## Can I read these files without special software? + +Yes. +Every file is JSON or JSON Lines (one JSON value per line), and [spec/](../spec/README.md) specifies every format. [The examples](examples.md) read a package with a few lines of Python. + +## Why not keep using PDFs and page numbers? + +A page number names a region, not a statement, and it changes between a preprint and the version of record. +An address names a sentence or a cell by its ID, such as `hale2026harmonic-damb#v3063qv`. +It can add a pin (the first six hex digits of the node's hash) and character offsets, which lets a reader check the address against the exact text ([spec/06 §6.1](../spec/06-anchors.md#61-addresses)). + +An ID encodes no page, position or kind. +The system mints it once from the document key, kind, text hash and occurrence, then freezes it ([spec/04 §4.2](../spec/04-identity.md#42-minting-node-ids)). + +## Why does a key end in four odd characters? + +`hale2026harmonic-damb` is the paper's key: the citation key a reader would use, then four characters of a hash of its DOI. +Citation keys alone collide, between a preprint and its published version or two papers by one author in one year; the hash settles that, and any tool that knows the DOI can recompute it. +A key is minted once and never recomputed, so a corrected title does not change a key someone has cited ([spec/02 §2.4](../spec/02-model.md#24-work-and-document-keys)). + +## Why are numbers stored as strings? + +Databases and JSON libraries rewrite numbers: `310.0` becomes `310` and `1.5260` becomes `1.526`, and the printed digits are part of what a paper says. +Canonical JSON, the byte-exact form used for hashing, writes numbers as ECMAScript writes a double, so it would erase the same difference. +A decimal that carries meaning is a string. +JSON numbers are for counts, indexes, offsets, sizes and geometry ([spec/01 §1.2](../spec/01-conventions.md#12-numbers)). + +## What happens when a better converter comes along? + +The system aligns the new reading with the established document, sentence by sentence. +A sentence the alignment pairs keeps its ID even where the readings disagree, which catches a lost superscript instead of accepting it. +Every disagreement, and every sentence found in only one reading, becomes a suspect, a doubtful reading raised for review. +Nothing changes until a correction passes the gate, the rules that refuse, for example, a digit change with no crop of the page image as evidence. + +Converting the same input again with the same converter mints the same IDs ([spec/05 §5.6](../spec/05-hashes.md#56-alignment), [spec/11 §11.4](../spec/11-corrections.md#114-the-gate), [spec/04 §4.2](../spec/04-identity.md#42-minting-node-ids)). + +## Do I need receipts, rights records and spot-checks for a personal library? + +You need no receipts and no spot-checks. +A receipt is a signed record that a named person compared nodes with the page image, and a spot-check is a second reviewer's sample of that work. +One person can leave both out. + +Each source file still carries a rights record, though the record can say little: the license as printed, a `basis` of `unknown`, and no uses, each of which then counts as unknown ([spec/14 §14.1](../spec/14-rights.md)). +The fields are defined so that a personal library loads into a team's store later without conversion ([spec/00 §0.4](../spec/00-introduction.md#04-status)). + +## Is a model allowed to correct a document? + +A model may propose corrections and answer suspects, under the same gate as a person, and its corrections record the model and the run as author. +Only a named person can sign a receipt, and a model's annotation stays `proposed` until a person confirms it ([spec/11 §11.2](../spec/11-corrections.md#112-every-correction-records), [spec/18 §18.3](../spec/18-layers.md#183-the-annotation)). + +## Why are annotations W3C Web Annotations? + +Tools that follow the W3C Web Annotation model can read the standard parts of these annotations. +A layer, the file that groups annotations, follows the [W3C Web Annotation Data Model](https://www.w3.org/TR/annotation-model/), a W3C Recommendation of 2017. +Each target holds an `AnchorSelector` carrying a `scienting-anchor/1` record, followed by a standard `TextQuoteSelector` for tools that do not know the anchor selector. +(The `scienting-` prefix is the formats' namespace, separate from the repository's name.) +The formats use no `TextPositionSelector` or `FragmentSelector`. + +The anchor adds what the standard selectors lack: the node's ID, its hashes, and a defined outcome (`current`, `changed-below`, `moved`, `reattached` or `stale`) when the text has changed. +The Web Annotation model alone is the better-established choice where an annotation needs none of that. +Whether a generic Web Annotation client displays an `AnchorSelector` is untested. +See [the comparison](comparison.md). + +## What is the difference between a claim and an annotation? + +A statement true independently of the paper, such as "K_r is the bond force constant of the AMBER energy", is a claim. +A claim has to be checked against evidence, so it belongs in a store of checked claims outside these formats, which define no claim semantics. + +A statement about reading the paper, such as "the authors pass quickly over the scaling here", is an annotation in a layer, attributed and unchecked ([spec/18 §18.1](../spec/18-layers.md#181-one-rule-decides-what-is-a-claim-and-what-is-a-layer)). + +## Can a team share notes on a paywalled paper? + +Yes, without sharing the paper. +A checks-only package withholds all text and keeps IDs, labels, pages, boxes and keyed hashes. +A public layer swaps each quotation for keyed hashes, under a key derived from the paper's page fingerprints, so a reader checks and shows it only over their own copy. +The hash must be keyed because anyone can recover a plain hash of a short text such as `310.0` by hashing guesses ([spec/12 §12.5](../spec/12-package.md#125-text-policies), [spec/05 §5.8](../spec/05-hashes.md#58-keyed-hashes), [spec/06 §6.3](../spec/06-anchors.md#63-keyed-anchors)). + +Whether a team may share notes on a paper this way is a question for its own counsel; nothing here is legal advice. + +## How does this differ from JATS or TEI? + +They overlap in subject, not in job. + +JATS, the [Journal Article Tag Suite](https://www.niso.org/publications/z3996-2024-jats) (ANSI/NISO Z39.96-2024), is an XML format for publishers and archives to exchange journal content. paperspec does not replace it. +A JATS file is one kind of witness (a source file), an input from which a document is established. +None of the 312 elements in the [JATS 1.4 Archiving tag library](https://jats.nlm.nih.gov/archiving/tag-library/1.4/) marks a sentence; its smallest text unit is the paragraph, `

`. + +TEI, the Text Encoding Initiative, has a sentence-like [`` element](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-s.html) and keeps both readings of a corrected passage with [`` and ``](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-corr.html). +The encoder assigns its `xml:id`, and the guidelines [recommend it for durability](https://tei-c.org/release/doc/tei-p5-doc/en/html/SA.html). +paperspec mints and retires IDs by rule, keeps corrections as separate records with evidence, and hashes each node. + +Keep JATS for publisher and archive exchange and TEI for general scholarly text encoding. +A TEI file is a witness of kind `xml` ([spec/02 §2.3](../spec/02-model.md)). +The full comparison is [docs/comparison.md](comparison.md) + +## What is its status and maturity? + +Version 0.1.0 has 32 formats: 19 are `candidate` and 13 are `provisional`, as [registry/formats.json](../registry/formats.json) lists. +A `candidate` format is complete, with vectors and fixtures, and ready to implement. +A `provisional` one is complete and expected to change as implementations gain experience. +The provisional formats are dataset, digitization, view, project, bundle, snapshot, draft-ids, exercise, submission, grade, checklist, log-entry and checkpoint. + +The repository holds a reference checker (`tools/check.py`), 25 vector files, five valid packages, one of them also as a zip, and 31 deliberately broken packages ([spec/00 §0.4](../spec/00-introduction.md#04-status), [spec/22](../spec/22-conformance.md)). + +## What does it not do? + +It is built for a team-scale corpus of hundreds of documents, not hundreds of millions of papers. +It does not replace publisher interchange formats; it reads JATS as a witness. +It does not fix what a converter reads wrongly. +It records the reading and raises disagreements as suspects, and a correction is checkable. +It is not a search engine, a citation index or a recommendation feed ([docs/overview.md](overview.md)). + +## How do I add a node kind or a run kind? + +A node kind is a type of document part, such as `sentence`; a run kind is a type of inline content within a sentence, such as `math`. +Propose either with the vector or fixture that shows it. +A new kind is a minor version ([spec/00 §0.3](../spec/00-introduction.md#03-format-identifiers-and-versions)). +See [CONTRIBUTING.md](../CONTRIBUTING.md). + +## What are the files in `tools/` for? + +`build.py` builds the fixtures and vectors. `check.py` recomputes and checks every one, and `load.py` loads packages into SQLite. +The `oracle/` modules compute every expected value, so that none is typed by hand. +They are not a library; implementations follow the specification ([tools/README.md](../tools/README.md)). diff --git a/docs/glossary.md b/docs/glossary.md new file mode 100644 index 0000000..3a8d7c1 --- /dev/null +++ b/docs/glossary.md @@ -0,0 +1,206 @@ +# Glossary + +A scientific paper changes after it is published: errata appear, readings get corrected, annotations pile up. paperspec is a set of file formats for scientific papers that keeps each sentence findable through those changes (repository: ). +This glossary defines its terms for readers from newcomer to expert, implementers included. +Each entry gives the plain meaning, then the precise one, then the chapter that defines it. + +A hash is a fixed-length fingerprint of data; changing one character changes it. +SHA-256 is the hash function the formats use. +The specification is at version 0.1.0, and each format is `candidate` or `provisional` in `registry/formats.json`. +Format names begin with `scienting-`, as in `scienting-doc/1`; that prefix is the formats' namespace, a separate matter from the repository's name. "Outside term" marks a standard from another project. + +Address +: A string that names one node, optionally pinned to its state by the first six digits of its `node_hash` and narrowed to a span of code points (numbered characters of text): `key#id@hash6[start:end]`. ([6.1](../spec/06-anchors.md#61-addresses)) + +Alias +: A legacy ID kept so that old references still lead to the node that now holds their text. ([4.3](../spec/04-identity.md#43-permanence-retirement-and-aliases)) + +Align key +: A hash of a node's lossy projection, used only to propose that two readings hold the same sentence; it never certifies anything. ([5.1](../spec/05-hashes.md#51-the-five-values)) + +Anchor +: The stored form of a pinned address, with its quotation and context, so that a reference can be found again after the text changes. +It resolves as current, changed below, moved, reattached or stale. ([6.2](../spec/06-anchors.md#62-the-anchor), [6.5](../spec/06-anchors.md#65-resolution)) + +Asset store +: Where a team keeps files by SHA-256: witnesses, images, crops and withheld text. ([12.6](../spec/12-package.md#126-assets)) + +Bundle +: One SQLite file with every table and a full-text index, which a reader or a store queries. +Format `scienting-bundle/1`, `provisional`. ([13.5](../spec/13-database.md#135-the-bundle)) + +Changed below +: The resolution of an anchor on a container that is unchanged in itself while something inside it changed. ([6.5](../spec/06-anchors.md#65-resolution)) + +Checklist +: A record of checking an export, such as accessible HTML, against a named standard, criterion by criterion; it is covered by the receipt of the person who checked. +Format `scienting-checklist/1`, `provisional`. ([8.11](../spec/08-fidelity.md#811-checklists)) + +Checkpoint +: A signed note that states a transparency log's size and root hash, which a verifier checks against the last checkpoint it saw. +Independent parties, the log's witnesses, cosign it, and a project says how many must. +Format `scienting-checkpoint/1`, `provisional`. ([23.2](../spec/23-log.md#232-checkpoints)) + +Correction +: An operation on an established document, with its evidence and author; never edited, only appended. ([11](../spec/11-corrections.md)) + +Description +: An annotation that describes a figure, panel or table for readers who cannot see it, as a short text equivalent (`alt`) or a full description (`long`); an accessible export uses confirmed descriptions only. ([18.4](../spec/18-layers.md#184-bodies)) + +DID +: Outside term. +A decentralized identifier (W3C). +A roster key may carry its `did:key`, which the public key alone determines, so a signer has one name inside and outside the store. ([8.7](../spec/08-fidelity.md#87-revocations-and-the-roster)) + +Document +: The text established for one version of one work, from one or more witnesses, as a tree of nodes. ([2.1](../spec/02-model.md#21-four-objects), [3](../spec/03-nodes.md)) + +Document key +: The work key, with a dotted suffix for any version other than the version of record: `.si` for Supporting Information, `.v2` for a second preprint. ([2.4](../spec/02-model.md#24-work-and-document-keys)) + +Drift +: The amount that has changed below a container since an anchor on it was made, counted from the corrections: the share of the container's leaves touched by later corrections. +It is reported as `none`, `low` or `high`, with a default threshold of a quarter. ([6.6](../spec/06-anchors.md#66-drift)) + +Exercise +: An annotation whose body holds a prompt, an answer key and a grading rule. +The key is anchors, a verdict, a chain, a value or planted errors, by exercise kind. ([19.1](../spec/19-exercises.md#191-exercises)) + +Fidelity level +: How far a leaf's text was checked against its source, from F0 converted to F3 proofread. ([8.1](../spec/08-fidelity.md#81-levels-of-fidelity)) + +History root +: The root of the Merkle tree over a document's corrections, kept in `document.json`, so a consistency proof can show that a later revision extends an earlier one. ([11.5](../spec/11-corrections.md#115-the-history-root)) + +JATS +: Outside term. +Journal Article Tag Suite, ANSI/NISO Z39.96-2024, an XML format in which publishers and archives exchange journal content ([the NISO page](https://www.niso.org/publications/z3996-2024-jats)). +In paperspec, `jats` is a witness kind: the fixture `okafor2025solvent-acth` was established from a JATS file and a PDF that agree. +The formats ingest JATS and do not replace it. ([2.3](../spec/02-model.md#23-witnessesjson)) + +Keyed hash +: A content value computed as an HMAC (a hash mixed with a secret key) under a team key or a key derived from page fingerprints, so a short text cannot be recovered by hashing guesses. ([5.8](../spec/05-hashes.md#58-keyed-hashes)) + +Layer +: A named set of annotations with one purpose, audience, visibility and license. ([18.2](../spec/18-layers.md#182-the-layer)) + +Leaf +: A node that holds text itself: a sentence, cell, reference, author line, keyword line, equation, equation line, code or algorithm. +A leaf anchor points at one whole. ([6.4](../spec/06-anchors.md#64-four-kinds-of-anchor)) + +Lossy projection +: A node's text with scripts flattened, citation marks, whitespace and dashes removed, and case folded; used for proposing alignments. ([5.5](../spec/05-hashes.md#55-the-lossy-projection)) + +Match hash +: A hash of a node's strict projection. +Two readings agree only when their match hashes are equal and their complex-notation keys are equal. +A complex-notation key is `notation:source` for a piece of math too complex for the formats to normalize, with the source's whitespace removed ([5.3](../spec/05-hashes.md#53-the-strict-projection)). ([5.1](../spec/05-hashes.md#51-the-five-values), [5.3](../spec/05-hashes.md#53-the-strict-projection)) + +ML-DSA-65 +: Outside term. +The lattice-based signature scheme of FIPS 204, believed to resist quantum computers. +A receipt may be signed with it today, beside Ed25519. ([8.4](../spec/08-fidelity.md#84-record-hashes-and-signatures)) + +Model +: The record of a machine-learning model that proposed a correction or wrote an annotation: its name, provider and version, and the hashes of its weights, instructions and parameters. ([11.2](../spec/11-corrections.md#112-every-correction-records)) + +Node +: An addressable part of a document: a section, paragraph, sentence, figure, panel, caption, table, row, cell, equation, footnote, reference and the rest. +Each node has a permanent ID and five content values; table columns and figure-text items have IDs and are not nodes. ([3](../spec/03-nodes.md), [4.2](../spec/04-identity.md#42-minting-node-ids)) + +Own hash +: A hash of a node's own content without its children, used to judge anchors on containers that have content of their own. +The `node_hash` is a hash of the own hash and the children's node hashes. ([5.1](../spec/05-hashes.md#51-the-five-values), [5.2](../spec/05-hashes.md#52-own-content)) + +Package +: A document as a folder, or a zip of one, of canonical JSON (a plain-text data format) and JSON Lines (one JSON value per line) files, with a manifest whose hash pins them all. ([12](../spec/12-package.md)) + +Page fingerprint +: A hash of a page's size, its text with download stamps removed, and its images, so that differently stamped downloads share their pages. ([7.1](../spec/07-geometry.md#71-page-fingerprints)) + +Plain projection +: A node's text as one string, on which offsets, quotations and text hashes are defined. ([3.6](../spec/03-nodes.md#36-the-plain-projection)) + +Policy +: A project owner's signed decision that settles rights a record leaves unknown. +It never overrides a use the record sets to true or false. ([14.2](../spec/14-rights.md#142-effective-uses)) + +Proof +: An RFC 9162 inclusion proof that one item was covered by a receipt, or a consistency proof that one history extends another, each a short list of hashes. +Format `scienting-proof/1`. ([8.5](../spec/08-fidelity.md#85-merkle-roots)) + +Project +: A team's curated set of documents, with its members, layers, data, reading paths and drafts. +Format `scienting-project/1`, `provisional`. ([20](../spec/20-projects.md)) + +Receipt +: One signature over a Merkle root of what a person reviewed in a sitting. +The signature sets the fidelity level of what it lists. +A Merkle root is a single hash that commits to a list of items; receipts build it as RFC 6962 (an internet standards document) describes, a tree that [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162) obsoletes and defines identically. ([8.3](../spec/08-fidelity.md#83-receipts), [8.5](../spec/08-fidelity.md#85-merkle-roots)) + +Revision +: The index of the last correction applied to a document, or 0 when there is none; anchors and receipts record it. ([11](../spec/11-corrections.md)) + +Revocation +: A signed record that withdraws a receipt, or every receipt by one signer in a period. ([8.7](../spec/08-fidelity.md#87-revocations-and-the-roster)) + +Rights record +: A witness's license, the basis on which the team holds it, and the uses that basis allows. ([14.1](../spec/14-rights.md#141-the-rights-record)) + +Roster +: The list of keys that may sign, with the person who holds each, that person's role in the team, and what the key may sign. ([8.7](../spec/08-fidelity.md#87-revocations-and-the-roster)) + +Selector +: Outside term. +In the W3C Web Annotation Data Model, the part of an annotation's target that says where in the source resource the annotation applies. +The model defines `TextQuoteSelector` (exact text, with optional prefix and suffix) and `TextPositionSelector` (offsets, which the model calls very brittle), among others ([the W3C model](https://www.w3.org/TR/annotation-model/)). +Layers use a custom `AnchorSelector`, which carries an anchor, followed by a `TextQuoteSelector` for tools that do not know it; they use neither `TextPositionSelector` nor `FragmentSelector`. ([18.3](../spec/18-layers.md#183-the-annotation)) + +Spot-check +: A second reviewer's check of a sample of a receipt's nodes, drawn from a seed nobody can steer: the checker's deterministic signature over the receipt's record hash. ([8.8](../spec/08-fidelity.md#88-spot-checks)) + +Stamp rule +: A pattern that recognizes a publisher's download stamp in a page's text, so that fingerprints ignore it. ([7.2](../spec/07-geometry.md#72-stamp-rules)) + +Strict projection +: A node's text with notation folded to one canonical form and structure kept; used for certifying agreement. ([5.3](../spec/05-hashes.md#53-the-strict-projection)) + +Suspect +: A doubtful reading raised for a person or a review session to answer. ([5.7](../spec/05-hashes.md#57-suspects)) + +Targeted F3 +: Proofreading the nodes a team's claims, quotations and datasets rest on, rather than every node. +The target set also includes the leaves of every anchored container, every equation and, under the project's digit rule (`all`, `anchored-sections` or `none`), sentences and cells with a digit in a text or math run (an inline stretch of plain text, or of TeX or Typst math, within the node; [3.5](../spec/03-nodes.md#35-inline-runs)). ([8.10](../spec/08-fidelity.md#810-targeted-f3)) + +Text leaf +: A leaf whose text a container's projections are made of: any leaf except an equation line, or an equation inside a sentence, whose text is already part of its equation or its sentence. ([3.6](../spec/03-nodes.md#36-the-plain-projection)) + +Text policy +: Whether a package carries its text (`full`) or withholds it (`checks-only`). ([12.5](../spec/12-package.md#125-text-policies)) + +Tile +: One file of a transparency log served statically: 256 hashes of one level of the tree, or 256 entries, so a client fetches only the subtrees it needs. ([23.4](../spec/23-log.md#234-serving-a-log)) + +Verdict +: A judgment of whether a cited passage supports a citing sentence: supports, partly, does not, or cannot tell. ([19.2](../spec/19-exercises.md#192-verdicts)) + +Version +: One expression of a work: a preprint, the version of record, an erratum, the Supporting Information. ([2.1](../spec/02-model.md#21-four-objects)) + +VRF +: A verifiable random function (RFC 9381): a keyed function with exactly one valid proof for each key and input, so that a spot-check seed can be checked but not chosen. ([8.8](../spec/08-fidelity.md#88-spot-checks)) + +Web Annotation +: Outside term. +The W3C Recommendation of 23 February 2017 for annotations with a body, a target and a motivation ([the W3C model](https://www.w3.org/TR/annotation-model/)). +It gives sentences no permanent IDs and reports no outcomes such as current or stale; for annotation in general, it and its clients are the better choice. +Layers are Web Annotations. ([18](../spec/18-layers.md)) + +Witness +: One file of one version of a work, identified by its SHA-256. ([2.1](../spec/02-model.md#21-four-objects), [2.3](../spec/02-model.md#23-witnessesjson)) + +Work +: A piece of scholarship across all its versions. ([2.1](../spec/02-model.md#21-four-objects)) + +Work key +: A work's permanent name: a Scholar-style citation key, a hyphen, and the first characters of a hash of the work's identity, such as `vaswani2017attention-a241`; minted once and never recomputed. ([2.4](../spec/02-model.md#24-work-and-document-keys)) diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..d06c2f3 --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,161 @@ +# The paperspec formats + +This page serves three readers. +A student new to the problem will find each term defined where it first appears. +A developer who will write a reader, writer, converter or checker will find each topic pointing to its chapter. +A researcher or standards author will find the status, the limits and a comparison stated outright. + +## The idea + +Scientists who rely on a paper keep asking two questions. + +1. + Does the cited passage say what is claimed? A citation to a real paper can still be inaccurate, incomplete or beside the point, so a reader needs to see the exact sentence it rests on. +2. + Where did this number come from, and how far was it checked? A force constant in a table, a value read off a plot, a parameter in a model: each should lead back to the cell or sentence it came from, with a record of who compared it with the page. + +Most tools for scientific literature aggregate. +They index hundreds of millions of papers and answer questions over all of them, shallowly. paperspec does the opposite. + +A team working on a focused question cares more about fifty papers it understands completely than about the world's literature. +Those fifty papers deserve to be converted once, corrected once, split down to the sentence, annotated by the people who know them, linked to checked claims, and kept. + +A model can summarize a paper. +It cannot give you a signed statement that a named person checked a passage, IDs that never move, or a store its owner controls. +The formats supply those three, and they are worth most at the scale of one team. + +paperspec is a set of file formats for scientific papers that have been converted, split into addressable pieces and checked. +The repository is at . +It is version 0.1.0 and defines 32 formats; in [registry/formats.json](../registry/formats.json), 19 are `candidate` and 13 are `provisional`. + +## Who it is for + +| User | Example | +| --- | --- | +| One researcher | A thesis student, a science writer or fact-checker, a Wikipedia editor checking a citation, a scientist keeping a deep personal library. | +| An academic lab | A research group, a thesis committee, a journal club reading one annotated paper together. | +| A course | An instructor whose students learn to check whether a source supports a claim, with answers that are addresses and can be graded. | +| An industrial team | A computational chemistry or materials group that needs to show which passage of which paper each parameter came from. | + +"Team" throughout means roughly five to twenty people with a few dozen to a few hundred papers that matter. +The design targets that scale: hundreds of documents (500 papers come to about a million and a half database rows). + +## What the repository contains + +The repository defines files and checks them. +It holds no application. + +The formats are identified as `scienting-/`, such as `scienting-doc/1`. +That prefix is the formats' namespace. +It appears inside hashed data and test vectors, and it is separate from the repository's name. + +| Folder | Holds | +| --- | --- | +| [spec/](../spec/README.md) | The specification, in 24 chapters (00 to 23). Normative. | +| [schemas/](../schemas/README.md) | 42 JSON (plain-text data format) Schemas for the files and records. | +| [registry/](../registry/README.md) | The list of formats, the rule IDs a checker reports, download-stamp rules, and default rights requirements. | +| [tools/](../tools/README.md) | Reference programs: `check.py` checks everything, `build.py` rebuilds the fixtures and vectors, `load.py` loads packages into SQLite, and `oracle/` is a compact implementation of every rule. | +| [vectors/](../vectors/README.md) | 25 files of test vectors: inputs and the exact outputs every implementation must compute. | +| [fixtures/](../fixtures/README.md) | Five valid example packages, one of them also as a zip, 31 deliberately broken ones that each break one named rule, example records, and the test keys that signed them. All text is synthetic. | +| [sql/](../sql/README.md) | Tables for SQLite, Dolt and PostgreSQL, and a SQLite bundle with full-text search. | +| [context/](../context/README.md) | The JSON-LD context that makes annotation layers W3C Web Annotations. | +| [docs/](README.md) | Guides, including this page. | + +## Roles + +The formats serve five roles. +A role is a job someone could implement. +The repository ships reference tools only for the checker and store roles. + +| Role | Does | +| --- | --- | +| Reader | Opens a package, resolves addresses and anchors, and shows text, annotations and each passage's fidelity level. | +| Writer | Produces files in these formats: nodes, corrections, receipts, annotations, datasets. | +| Converter | Turns a witness (a PDF, JATS XML, the article format publishers use, a LaTeX source archive, an HTML page, an EPUB or a Typst project) into a package and raises doubtful readings as suspects (flagged disagreements awaiting review). | +| Checker | Recomputes hashes, validates files against their schemas and reports broken rules by rule ID. `tools/check.py` does this for the repository. | +| Store | Keeps packages and records in a database a team can clone. `tools/load.py` loads packages into SQLite. | + +The [specification's reading paths](../spec/README.md) say which chapters each role needs. + +## How a paper moves through the formats + +1. + Acquire. + A witness arrives with a rights record that says how the team holds it and what that allows. + A witness is one file of one version of a paper, such as the publisher's PDF, identified by the SHA-256 hash of its bytes. +2. + Read and reconcile. + A converter reads the witness with one or more backends, aligns the readings sentence by sentence and compares them. + Each page gets a fingerprint with download stamps removed, and differently stamped downloads of one page are recognized as the same. +3. + Segment and mint. + Text is split into sentences. + Every node (a section, paragraph, sentence, figure, panel, caption, table, row, cell, equation, footnote or reference) gets a permanent ID and five content hashes. + A hash is a fixed-length fingerprint of content: change one character and it changes. +4. + Review. + Disagreements between readings become suspects with page crops. + A person or a model answers each as a correction, and the gate refuses any correction that changes a digit without image evidence. + In the example paper the first reading has a cell `3l0.0` where the page says `310.0`. +5. + Package. + The result is a package: a folder of canonical JSON files (JSON written in one fixed form, so equal content gives equal bytes) with a manifest whose hash pins the whole. + Five files are required (`MANIFEST.json`, `document.json`, `nodes.jsonl`, `witnesses.json`, `provenance.json`). + These are optional: `pages.jsonl`, `locations.jsonl`, `references.jsonl`, `corrections.jsonl`, `receipts.jsonl`, `ids.jsonl`, `suspects.jsonl`, `roster.json`, `assets/`, `datasets/` and `derived/` ([chapter 12](../spec/12-package.md)). +6. + Use. + A store loads the package into a database. + A reader renders it with layers of annotations. + Anchors (stored references to a sentence, with its hash and a quotation) let a claim, a dataset value or a draft's citation point at a passage. + Datasets, drafts, views, projects, exercises, checklists and the transparency log are `provisional` formats. +7. + Check and sign. + People proofread what matters and sign receipts; second reviewers spot-check them. + A passage is at level F3 (proofread) only while a valid receipt lists it at its current hash. + Every level counts only at the current text. + +[The walkthrough](walkthrough.md) follows one paper through every step. + +## Principles + +| Principle | Means | +| --- | --- | +| Quality over quantity | A small corpus processed to a stated and checkable fidelity beats a large one processed to an unknown one. | +| Do the work once | Conversion, correction, segmentation and digitization are recorded and kept. A fresh conversion of the same input mints the same IDs. A different converter's reading is aligned with the established text: sentences the alignment pairs keep their IDs, and every difference becomes a suspect. | +| Address everything | Every node has a permanent ID and five content hashes. Table columns and figure-text items also have IDs. They are not nodes and have no five hashes. IDs encode no page, ordinal or kind; each is minted once from the document key, kind, text hash and occurrence, then frozen. | +| Keep source and commentary apart | What a source says is stored as the source said it. Everything people or models add is stored beside it and points at it. | +| Count only what was done | A level says how far something was checked, and it falls back when the checked content changes. | +| Models propose, people sign | Models may draft, segment, gloss and digitize, and a model's annotation stays `proposed` until a person confirms it. The proofread level comes only from a receipt signed by a named person. | +| The team owns its data | Packages are folders of JSON files, the database form is plain SQL tables, and every format is documented in the specification. A team can clone, read and keep its data without anyone's software. | + +## How it compares + +paperspec adds to existing standards and replaces none of them. [The comparison page](comparison.md) has the full account; five points follow. + +- JATS is the NISO standard by which [publishers and archives exchange journal content](https://www.niso.org/publications/z3996-2024-jats). + Its [version 1.4 element list](https://jats.nlm.nih.gov/archiving/tag-library/1.4/) shows no sentence element. + A JATS file is an input here (witness kind `jats`). +- TEI has a [sentence-like element](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-s.html) and [markup that keeps both readings of a correction](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-corr.html), and recommends `xml:id` pointers ["for durability in the presence of editing"](https://tei-c.org/release/doc/tei-p5-doc/en/html/SA.html). paperspec mints and retires IDs by rule and keeps corrections as a separate, evidence-gated record. + TEI is built for encoding scholarly text in general, including correction markup within a text. +- GROBID [converts PDFs to TEI](https://grobid.readthedocs.io/en/latest/Introduction/) and [reports F1 scores](https://grobid.readthedocs.io/en/latest/Introduction/) for its automatic reading. + Its output can be held as one reading, under witness kind `xml`. +- The W3C Web Annotation Data Model is [a Recommendation of 2017](https://www.w3.org/TR/annotation-model/). + Layers are Web Annotations, with a custom `AnchorSelector` followed by a standard `TextQuoteSelector` fallback. + The W3C model calls the `TextPositionSelector` ["very brittle"](https://www.w3.org/TR/annotation-model/) against changes to the resource, and the anchors here pin a hash instead. + For annotation in general, use the W3C model. +- Docling's [document schema](https://raw.githubusercontent.com/docling-project/docling-core/main/docs/DoclingDocument.json) refers to items by position (`#/texts/12`) and lists no per-item hash field. + Docling is a conversion toolkit that, [by its own abstract](https://arxiv.org/abs/2501.17887), uses AI models for layout analysis and table structure recognition. paperspec defines no converter. + +The formats are at version 0.1.0, the repository names no outside adopter, and the reference tools belong to the same repository. +The formats do not replace publisher interchange formats. +They also do not fix what a converter reads wrongly; they record it and make it checkable. + +## What it is not + +It is not a search engine over all literature, a citation index, a recommendation feed or a chat-with-any-PDF tool. +Tools may import from Crossref, OpenAlex, PubMed Central or arXiv, and none should depend on them to work. + +## Where next + +- [Concepts](concepts.md) explains each idea with an example. +- [The specification](../spec/README.md) defines each format exactly. diff --git a/docs/rationale.md b/docs/rationale.md new file mode 100644 index 0000000..b2b037d --- /dev/null +++ b/docs/rationale.md @@ -0,0 +1,320 @@ +# Rationale + +Each choice below is one a reader is likely to question. +The specification states the rule, and this page gives the reason. + +This page is for newcomers, implementers and experts. +Newcomers find each term defined where it first appears. +Implementers find the chapter that defines each rule. +Experts find the cost of each choice and, where a neighboring standard chose differently, how it differs (the full comparison is in [comparison.md](comparison.md)). + +The formats are at version 0.1.0. +Of the 29 in `registry/formats.json`, 19 are `candidate` and 13 are `provisional`, and the provisional ones are named where they appear. +The repository is paperspec, at . +The `scienting-` prefix in format names such as `scienting-anchor/1` is the formats' namespace, separate from the repository's name. + +## Identity + +### IDs carry no meaning + +Every sentence, cell and other node has an ID, a short name that other records use to point at it. +An ID that encoded a page, an ordinal or a kind would change when a converter orders blocks differently, or when a paragraph turns out to be a caption. + +An ID is minted once from the document key, the node's kind, the hash of its text and an occurrence count that separates identical texts, and is then frozen ([spec/04 §4.2](../spec/04-identity.md#42-minting-node-ids)). +A reclassification leaves it as it was, and a fresh conversion of the same input mints the same IDs. +A different converter mints different ones for some sentences: those the alignment pairs with the established reading keep their IDs, and every difference becomes a suspect for review ([spec/05 §5.6](../spec/05-hashes.md#56-alignment)). + +A content address such as an [IPFS content identifier](https://docs.ipfs.tech/concepts/content-addressing/) or a [Software Heritage identifier](https://www.swhid.org/specification/v1.2/5.Core_identifiers/) is a function of content at all times. +That suits immutable data and archived source code. +Any correction would rename the sentence. +Here the ID is derived from content once and kept apart from the content hashes, so the pair of ID and hash says whether the text changed. + +The cost is that two conversions that read a sentence differently by one character mint different IDs for it. + +### IDs never move, and retired IDs leave a trail + +Everything a team builds points at IDs: notes, claims, dataset values, citations in drafts. +A merge records its successor, a deletion records that there is none, and legacy IDs live on as aliases, all in `ids.jsonl` ([spec/04 §4.3](../spec/04-identity.md#43-permanence-retirement-and-aliases)). + +### Work keys carry a hash + +A citation key such as `vaswani2017attention` is what readers say, and it collides: a preprint and its published version, or two papers by one first author in one year with the same first title word, would share it. +Four characters of a hash of the work's identity, its DOI when it has one, settle the collision and let any tool holding the DOI recompute the key. +The key is minted once and never recomputed, so a corrected title cannot change a name someone has cited; when two works still share four characters, the later one gets six ([spec/02 §2.4](../spec/02-model.md#24-work-and-document-keys)). +The rule is the one the studio's reading-list tool already uses, so a paper keeps its key from the reading list to the store. + +### Identifiers are tag URIs + +Layers, annotations and documents name themselves with `tag:scient.ing,2026:` URIs (RFC 4151) rather than `urn:` names, because a URN namespace must be registered with IANA and this one is not. +A tag URI needs only a domain and a date, and these identifiers sit inside hashed annotations, so the cheap time to choose was before release. + +### Revisions are counted, not timed + +Anchors are made on different machines and packages are imported later, and clocks disagree. +A correction index does not disagree with itself. +A document's revision is the index of its last correction ([spec/06 §6.2](../spec/06-anchors.md#62-the-anchor), [spec/11](../spec/11-corrections.md)). + +## Hashes and projections + +A hash is a fixed-length fingerprint of data: equal data gives equal hashes, and any change gives a different one. +Every hash here is SHA-256 ([spec/01 §1.3](../spec/01-conventions.md#13-hashes)). +A projection is a rewritten form of a text, made only to be hashed. + +### Canonical JSON + +Canonical JSON is JSON (JavaScript Object Notation, a text format for structured data) written in exactly one way, so equal data always hashes the same. +The formats use the JSON Canonicalization Scheme, [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) (an RFC, or Request for Comments, is a numbered Internet standards document), which requires numbers to be IEEE 754 doubles (IEEE is the Institute of Electrical and Electronics Engineers) (the standard binary floating-point numbers), and add one rule: a decimal that carries meaning is a string, so `310.0` and `1.5260` keep their printed digits ([spec/01 §1.1 and §1.2](../spec/01-conventions.md)). +The cost is that a reader must treat those strings as decimals itself. + +### Five values, not one + +A text node carries five values ([spec/05 §5.1](../spec/05-hashes.md#51-the-five-values)), because no single hash does all of their jobs. + +- Quotations need every character, so `text_hash` covers the normalized text. +- Certifying that two witnesses agree needs notation folded but structure kept, which is `match_hash`. + A witness is one file the text was read from. +- Proposing that two sentences are the same needs something looser still, which is `align_key`. +- Containers need a hash of their own content, `own_hash`, apart from the `node_hash` that also covers what they hold. + +Table columns and figure-text items have IDs but are not nodes, so they carry no hashes ([spec/09 §9.1](../spec/09-figures-tables-equations.md)). + +### Only the strict projection certifies + +OCR (optical character recognition, which reads text from page images) drops superscripts. +A projection loose enough to match "103" with 10³ would certify an error, because the printed value is 1000 and the reading is 103. +The lossy key may propose that match. +Only the strict hash may accept it, and then only when the complex-math keys agree too ([spec/05 §5.3](../spec/05-hashes.md#53-the-strict-projection)). + +### Citation marks stay marked in the strict projection + +"10" followed by citation 3 would agree with the text "103" without the marks. + +### Decimal points and commas count as simple notation + +Simple math is rewritten to one linear form that can match plain text; anything else is complex and is compared by its source. `$-1.5$` in a LaTeX source would be complex math without the two characters, and could never agree with "−1.5" in the PDF ([spec/05 §5.4](../spec/05-hashes.md#54-simple-notation)). + +### A hyphen or en dash before a digit is a minus sign in the strict projection + +Text layers and OCR disagree about dashes in "10–20" and "−5". +Folding them before digits makes witnesses agree without touching a dash inside a name such as "CT–CT". + +### The lossy key deletes whitespace and dashes + +OCR merges and splits words and line-break hyphens, and a key that only proposes alignments should forgive that. +It also folds case ([spec/05 §5.5](../spec/05-hashes.md#55-the-lossy-projection)). + +### Offsets index the stored text, and structural hashes cover it exactly + +An offset counts Unicode code points, the numbered characters of Unicode, into the node's stored plain text ([spec/01 §1.5](../spec/01-conventions.md#15-character-offsets)), and own content is hashed as stored. +Every stored offset is still exact when `node_hash` is unchanged, and a renderer can slice the stored text without normalizing it first. +Only the three text values, `text_hash`, `match_hash` and `align_key`, normalize. + +### The character data is pinned to one Unicode version + +Normalization and General Categories change between Unicode versions, and both enter every hash. +The chapters pin Unicode 16.0, the reference tools refuse to run on another version, and moving to a later one is a change to every text-hashing format ([spec/01 §1.4](../spec/01-conventions.md#14-text-normalization-for-hashing)). + +### Hashes that leave the team are keyed + +A plain hash of "310.0" is recovered by hashing guesses, and overlapping anchors can rebuild passages. +Inside a team, plain hashes are fine. + +An export to another machine of the team uses an HMAC (hash-based message authentication code), a hash that needs a secret key, under the team key. +A public layer, or any export of a work whose text is withheld, uses a key derived from the paper's own page fingerprints, which only someone holding the paper can compute ([spec/05 §5.8](../spec/05-hashes.md#58-keyed-hashes)). + +## Anchors + +An anchor is a stored pointer to a node or to a quoted span inside it, with enough context to find it again after the text changes ([spec/06](../spec/06-anchors.md)). + +The [World Wide Web Consortium (W3C) Web Annotation model](https://www.w3.org/TR/annotation-model/) also anchors with quotations: its `TextQuoteSelector` takes `exact`, `prefix` and `suffix`, and its `TextPositionSelector` is described there as very brittle. +An anchor here keeps the quote with up to 32 code points of prefix and suffix and adds hashes, so resolution has exact outcomes (`current`, `changed-below`, `moved`, `reattached`, `stale`). +Hypothesis, in [its description of its own anchoring](https://web.hypothes.is/blog/fuzzy-anchoring/), matches fuzzily. + +Annotation layers use a custom `AnchorSelector` followed by a standard `TextQuoteSelector` fallback for tools that do not know ours ([spec/18 §18.3](../spec/18-layers.md)). +The cost is a selector type no generic tool defines. +For annotation in general, the W3C model is the better choice. + +### Every anchor carries `own_hash`, and anchors on containers without content carry their leaves + +Telling a relabel from a real change needs the anchored `own_hash`. +Deciding whether a merged paragraph still holds "at least half" of what was anchored needs the original leaves. + +### Long quotations become a hash and a length + +Quotations over 200 code points are replaced by a hash and a length, which keeps anchors small and limits how much text an anchor carries. +A hashed window can still be found again in the node. + +### Prefix and suffix pick between repeated quotes + +"The value" may occur twice in a sentence. +The context around it decides which one was meant. + +### `changed-below` reports drift + +A note on a section stays valid when a typo inside it is fixed. +By default the drift is `high` once the leaves touched by corrections since the anchor was made exceed a quarter of the leaves involved, and the note is then flagged for review ([spec/06 §6.6](../spec/06-anchors.md#66-drift)). + +### A row's header path is not hashed + +Rows have no content of their own, and a row's `header_path` is not part of it. +Inserting a dropped row-group header does not stale the anchors on every cell beneath it ([spec/09 §9.2](../spec/09-figures-tables-equations.md)). + +## Corrections + +### Corrections are appended, never edited + +A document's history is its first reading plus its corrections, so anyone can see what changed, when and why, and on what evidence ([spec/11](../spec/11-corrections.md)). + +### Corrections include a `set` operation + +Readings drop spans, roles and header paths, not only words, and those need a correction too. + +### Applied corrections record what they touched + +Drift is computed from the records alone, with no need to replay history, because each record carries `path`, `to_path` and `touched` ([spec/11 §11.3](../spec/11-corrections.md#113-applied-fields)). + +### The history has a root + +Corrections are append-only in principle, but nothing in a package proved that a later revision extends an earlier one rather than rewriting it. +A Merkle root over the corrections in `document.json`, with RFC 9162 consistency proofs between revisions, does ([spec/11 §11.5](../spec/11-corrections.md#115-the-history-root)). + +### Digits need image evidence + +A wrong digit changes a result without looking wrong, so no digit changes without a crop of the page as evidence, and no leaf outside the correction's `touched` list may end up with different digits ([spec/11 §11.4](../spec/11-corrections.md#114-the-gate)). + +## Geometry + +### Pages have fingerprints + +Publishers stamp each download, so file hashes cannot identify a paper across teammates' copies. +Fingerprints with the stamps removed can ([spec/07 §7.1](../spec/07-geometry.md#71-page-fingerprints)). + +### Fingerprint text deletes whitespace entirely + +PDF text extractors disagree about where to insert spaces, and the fingerprint must come out the same in any two implementations. + +## Review + +### People sign receipts + +Nobody signs three thousand times, so one signature covers a Merkle root of everything reviewed in a sitting. +A Merkle tree hashes items in pairs, then those hashes in pairs, up to one root, and allows a proof that one node was covered without revealing the others. + +The receipt tree follows [RFC 6962](https://www.rfc-editor.org/rfc/rfc6962), whose replacement [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162) defines the same tree. +The specification makes a receipt with no items invalid, where the RFC hashes the empty list ([spec/08 §8.5](../spec/08-fidelity.md#85-merkle-roots)). +The tree is not the one behind `node_hash`, which hashes each node's `own_hash` with its children's `node_hash` values. + +### Spot-check seeds are VRF proofs + +A seed the reviewer could influence could be ground until the sample fell on careful work, and a seed the checker could vary could be ground by the checker. +An earlier draft used the checker's Ed25519 signature and called it unchoosable because signing is deterministic; that holds only for an honest checker, since a verifier accepts any valid signature and a dishonest one can sign with any nonce. +A verifiable random function (RFC 9381) has exactly one valid proof for a key and an input, which is the property the rule needs, and its keys are ordinary Ed25519 keys, so the roster needs nothing new. +Anyone can verify the proof and recompute the sample ([spec/08 §8.8](../spec/08-fidelity.md#88-spot-checks)). + +### A receipt can be proven without being shown + +The receipt tree follows RFC 9162 so that an inclusion proof, a dozen hashes, shows a buyer that one cell was proofread without handing over the receipt or the other nodes ([spec/08 §8.5](../spec/08-fidelity.md#85-merkle-roots)). +A transparency log of receipts, revocations and rosters ([spec/23](../spec/23-log.md)) uses the same tree and the checkpoint format transparency logs share, so that a receipt's time and the roster that governed it stop being self-asserted. + +### Error rates are reported as bounds + +One clean sample of ten proves little. +A one-sided Clopper–Pearson upper bound, by default at confidence 0.95, across all of a reviewer's samples says what can be claimed. +With no errors it is about 3 divided by the number sampled ([spec/08 §8.9](../spec/08-fidelity.md#89-reviewer-error-bounds)). + +### Levels fall back + +A node counts as proofread only through a valid receipt that lists it at its current `node_hash`, so a correction never leaves a stale "proofread" behind ([spec/08 §8.1](../spec/08-fidelity.md#81-levels-of-fidelity)). + +## Rights + +### Rights are recorded per witness + +What a team may do depends on how it obtained the paper: a subscription, a mining license, an open license, its own work. + +### AI uses have two axes + +Reviewers ask whether a model may see the text, where it runs, and whether the text is kept there. +The record names a purpose, `internal` or `external` depending on whether results leave the organization, and a processor: `local`, `tenancy`, `outside-no-retention` or `outside` ([spec/14 §14.1](../spec/14-rights.md#141-the-rights-record)). + +### Unknown means no + +A stage whose rights are unknown does not run. +A project owner settles the question with a signed policy, so the decision is the team's and is on the record. +A policy fills in unknowns and never overrides an explicit answer. + +A project setting can turn the refusal into a warning. +The refusal is the default, and the project format is `provisional` ([spec/20](../spec/20-projects.md)). + +### Backend licenses are part of the gate + +A converter's code and its model weights can be licensed differently, and the weights may exclude commercial or competing use. +A condition whose answer is unknown counts as not met ([spec/14 §14.4](../spec/14-rights.md#144-backends-and-profiles)). + +## Packages and databases + +### Canonical JSON, one record per line + +A corrected sentence is a one-line diff, and every file has exactly one valid byte sequence, so a hash of the manifest pins the whole package ([spec/01 §1.9](../spec/01-conventions.md#19-files), [spec/12 §12.3](../spec/12-package.md#123-the-manifest)). + +A [Frictionless Data Package](https://datapackage.org/standard/data-package/) lists resources with an optional `hash` that defaults to MD5 (an older hash function). +The package manifest here lists every other file with SHA-256 and size. +The dataset format, which is `provisional`, is a Data Package with units, uncertainty, an origin and anchors to the printed values added ([spec/15](../spec/15-datasets.md)). + +Two neighboring standards cover other parts of this ground, RO-Crate and the PROV Ontology. + +[RO-Crate](https://www.researchobject.org/ro-crate/) describes research data with schema.org annotations in JSON-LD, and it is the better choice for general description and discovery. +No mapping between it and these packages is defined. + +Provenance is a plain `provenance.json` of tools, backends, cached readings and stages. +It is not the [PROV Ontology](https://www.w3.org/TR/prov-o/), which other systems can query generically. + +### Checks-only packages drop everything that carries text + +Corrections carry their find and replace strings, datasets carry values, suspects carry the readings compared, and figure text and reference records carry text. +A checks-only export omits them all, withholds the content of every leaf, and keys its hashes ([spec/12 §12.5](../spec/12-package.md#125-text-policies)). + +### SQL avoids reserved words in every engine + +The same tables run on SQLite, Dolt (MySQL-compatible) and PostgreSQL, and no name is a word reserved in any of the three. +The formats' `key`, `index`, `at`, `by`, `before` and `after` become `doc_key`, `idx`, `made_at`, `signer`, `before_hash` and `after_hash` ([spec/13 §13.1](../spec/13-database.md#131-portability)). + +### Loading and unloading are exact inverses + +A team can keep its documents in a database and still hand anyone the package, byte for byte. +The conformance suite checks this for every fixture ([spec/13 §13.3](../spec/13-database.md#133-load-and-unload)). + +## Questions the formats leave open + +These are settled for now, and a future version may revisit them. + +| Question | Current answer | +| --- | --- | +| Should node IDs carry a kind prefix, such as `s-k3m9q2a`, to help people debugging? | No: a reclassified node keeps its ID, so a prefix would become wrong. | +| Should `text_hash` normalize Unicode, or only collapse whitespace? | Both: Unicode Normalization Form C, then whitespace collapsed to single spaces and trimmed ([spec/01 §1.4](../spec/01-conventions.md#14-text-normalization-for-hashing)). | +| How long may a quotation in an anchor be? | 200 code points. | +| How is complex math compared? | By its source, run by run; comparing canonical MathML is a possible later addition. | +| What extension and media type do zipped packages use? | `.sct.zip` and `application/vnd.scienting.doc+zip`. | +| Which drift threshold, spot-check rate and digit rule should teams use? | By default, drift is high above a quarter of the leaves involved, and spot-checks sample 5% of a receipt's nodes, at least ten. The digit rule is `all`, `anchored-sections` or `none`; each is set per project. | +| How should rights combine when a document comes from witnesses held on different bases? | The most restrictive witness governs each use. | + +## Looking ahead + +Choices made so that the formats still serve in the 2030s, and the ones deliberately left open. + +- `ml-dsa-65` (FIPS 204) is a signature scheme a receipt may carry today, with a pure-Python reference implementation that reproduces NIST's test vectors, so a team can sign with a post-quantum key before Ed25519 is deprecated and verify such receipts decades on. + `cose` is reserved for the IETF's SCITT transparency services; a consumer treats an unimplemented scheme as invalid, so adopting it is a minor version ([spec/08 §8.4](../spec/08-fidelity.md#84-record-hashes-and-signatures)). +- Every hash is SHA-256, and `document.json` names the function, so a later algorithm is a new major version that can share a store with this one rather than a silent reinterpretation ([spec/01 §1.3](../spec/01-conventions.md#13-hashes)). +- A roster key may carry its `did:key`, which the public key determines, so a signer has one name inside and outside the store ([spec/08 §8.7](../spec/08-fidelity.md#87-revocations-and-the-roster)). +- A model that proposes a correction or an annotation is named by its weights, instructions and parameters by hash, and by where it ran ([spec/11 §11.2](../spec/11-corrections.md#112-every-correction-records)). +- The transparency log has a static tile layout, witnesses in the roster, and an acceptance rule in the project's settings; what remains is to run one ([spec/23](../spec/23-log.md)). +- The VRF reference implementation proves in about 5 ms and verifies in about 4 ms in plain Python, which is fine for fixtures and small logs; a production verifier can use any RFC 9381 library, since the proofs are the standard's bytes. + +## Known limits + +- Notation drops spaces and text keeps them, so `$T = 300$` from a LaTeX source and "T = 300" from a PDF disagree, and become a `word` suspect for review. +- Page fingerprints are computed from extracted text lines. + Two implementations that should agree on fingerprints must extract lines the same way. +- The formats are built for a team-scale corpus of hundreds of documents. + They do not replace publisher interchange formats, and they do not fix what a converter reads wrongly. + They record it and make it checkable. diff --git a/docs/walkthrough.md b/docs/walkthrough.md new file mode 100644 index 0000000..81c2ff3 --- /dev/null +++ b/docs/walkthrough.md @@ -0,0 +1,185 @@ +# Walkthrough: one paper, start to finish + +This guide follows the example paper `hale2026harmonic-damb` from a flawed first reading to a corrected, reviewed and signed document. +The paper is synthetic, written for the fixtures. +Its problems are modeled on the failures that the specification's rules address. + +Three readers can use the guide, and each gets something different. +A newcomer knows what a paper and a citation are, not hashes or JSON, so every term is defined where it first appears. +An implementer who will write a reader, writer, converter or checker gets the chapter and test vector for each step. +An expert gets the status: [paperspec](https://git.scient.ing/infra/paperspec) is at version 0.1.0, and each format is `candidate` or `provisional` in [`registry/formats.json`](../registry/formats.json) (19 candidate, 13 provisional). +The `scienting-` prefix on format names, as in `scienting-doc/1`, is the formats' namespace. +It has nothing to do with the repository's name. + +Open [fixtures/packages/hale2026harmonic-damb/](../fixtures/packages/hale2026harmonic-damb/) beside this page, because every ID below is in it. +A package is a folder of files, mostly JSON Lines (`.jsonl`: one JSON record per line). +The hand-written source of the first reading is [fixtures/src/hale2026harmonic.json](../fixtures/src/hale2026harmonic.json); no converter ran on it, and [`tools/build.py`](../tools/build.py) expands it into the package. +Each step says what a converter, a person or a checker does. + +## 1. A PDF arrives + +The team downloads the publisher's PDF. +The file becomes a witness, identified by its SHA-256 (a 64-digit hash that changes if any byte changes), with the short ID `qptsanv` ([spec/02](../spec/02-model.md)). +A person records its rights, meaning what the team may do with the file ([spec/14](../spec/14-rights.md)). +The library's subscription allows reading, text mining, and AI processing on the team's own machines for internal use, until August 31, 2027. +Whether it allows processing in the team's cloud is unknown. + +The publisher stamped the download in the margin with the institution and the time, so two downloads rarely share a SHA-256. +A page fingerprint avoids the problem of downloads that differ in their stamps. +It is a hash of a page's text, size and images after the stamp lines are removed ([spec/07](../spec/07-geometry.md)), and the rules `downloaded-via` and `sharing-guidelines` fired on both pages (see [`pages.jsonl`](../fixtures/packages/hale2026harmonic-damb/pages.jsonl)). +Page 101's fingerprint is `6272e6f3…` in this copy, stamped October 11, 2026, and in a second download from another institution, stamped March 2, 2027 ([vectors/fingerprints.jsonl](../vectors/fingerprints.jsonl)). + +## 2. The first reading, with its mistakes + +A converter reads the PDF into sections, paragraphs, sentences, a figure, a table, an equation, a footnote and references. +Each of these is a node, and each node gets a permanent ID: seven characters minted once from the document key, the node's kind, a hash of its text and an occurrence count, then frozen ([spec/04](../spec/04-identity.md)). +An ID encodes no page, order or kind, so it keeps naming the node after the text is corrected. + +Like every reading, this one has mistakes: + +| What the reading did | What the page says | +| --- | --- | +| A cell read `3l0.0`. | `310.0`, with the digit 1. | +| A sentence read `Values below 10-3 kcal mol⁻¹…`. | A superscript: 10⁻³. | +| Two sentences ran together: "…treated as zero. Table 1 lists…". | Two sentences. | +| One sentence was cut in two at a line break: "…and the energies were" and "fitted by least squares." | One sentence. | +| A paragraph was split at a column break. | One paragraph. | +| The running head "J. Example Chem. 2026, 14, 101–109" became a paragraph. | A running head, not text. | +| The equation's number read `(l)` and the figure's `Figure l`. | `(1)` and `Figure 1`. | +| The CT–HC row merged two cells into "338.7 1.0900". | Two cells. | +| The OW–HW row was missing. | It is there. | +| "Set B" spanned one column. | It spans two. | + +The converter does not guess. +Each doubtful place becomes a suspect, with a crop (an image cut from the page) for a person to answer ([spec/05 §5.7](../spec/05-hashes.md)). +Unresolved suspects travel in `suspects.jsonl`, which this package does not need. +Nothing changes until a correction passes the gate ([spec/11](../spec/11-corrections.md)). + +## 3. Twelve corrections + +Each fix is appended to [`corrections.jsonl`](../fixtures/packages/hale2026harmonic-damb/corrections.jsonl), numbered, with its evidence (a crop, or a person who read the page), its author (`ana` throughout) and its reason. + +| # | Operation | On | What it did | +| --- | --- | --- | --- | +| 1 | `replace` | cell `c20cna6` | `3l0.0` to `310.0`. A digit changed, so the gate required a crop, and it has one. | +| 2 | `replace` | sentence `ec5jc93` | `10-3` to the runs `10` and superscript `−3`. | +| 3 | `split` | sentence `ec5jc93` | Split before "Table 1"; the first part keeps `ec5jc93`, the second is new: `a4jrz2t`. | +| 4 | `merge` | sentence `xjns57z` | Joined with `ayea71r`, which is retired with `xjns57z` as its successor. | +| 5 | `merge` | paragraph `gwzbj3s` | Joined with `ncx2v4f`, retired the same way. | +| 6 | `delete` | paragraph `v8e4z6z` | The running head is gone; its IDs are retired with no successor. | +| 7 | `relabel` | equation `tkxsmts` | `(l)` to `(1)`. | +| 8 | `delete` | row `rncchma` | The garbled CT–HC row and its four cells. | +| 9 | `insert` | row `kx2kz2y` | The CT–HC row, read again: five new cells. | +| 10 | `insert` | row `ke0jxpn` | The missing OW–HW row. | +| 11 | `set` | cell `xyy7x6c` | Set B's `colspan` from 1 to 2. | +| 12 | `relabel` | figure `v7cx6qs` | `Figure l` to `Figure 1`. | + +The document is now at revision 12. +No uncorrected cell, sentence or row changed its ID or its hashes. +Only corrected nodes and their ancestors got new `node_hash` values; the sentence `rr20tev` is one of the ancestors, because it holds the relabeled equation. +Inserting a row adds a row node. +The table's own hash (`own_hash`) covers only its label and column definitions, so every other cell, and every value already taken from them, is untouched. + +## 4. IDs that never move + +The sentence about water is still `hca6dc5` after twelve corrections, the corrected cell is still `c20cna6`, and the sentence that lost its superscript is still `ec5jc93`. +The retired IDs are recorded in [`ids.jsonl`](../fixtures/packages/hale2026harmonic-damb/ids.jsonl), so anything that pointed at them can follow the trail. +Legacy aliases are recorded there too: `b-p01-text-003`, the ID an older tool gave the water sentence, still leads to `hca6dc5`. + +A fresh conversion of the same input mints the same IDs. +A reading by a different converter is aligned with this document sentence by sentence ([spec/05 §5.6](../spec/05-hashes.md), pinned by [vectors/alignment.jsonl](../vectors/alignment.jsonl)). +Sentences the alignment pairs keep their IDs, and every difference becomes a suspect rather than a silent change. +Sentences it cannot pair are recorded as dropped or added. + +## 5. What happened to the notes + +An anchor is the stored pointer behind a note or citation. +It holds a node's ID, the node's hashes when the anchor was made, the revision, and, for part of a sentence, the quoted words with context ([spec/06](../spec/06-anchors.md)). +The team had already made seventeen anchors pointing into the first reading at revision 0, before any correction. + +Resolving an anchor gives one of five results: + +- `current`: nothing changed. +- `changed-below`: the node is unchanged, and something under it changed. +- `moved`: the node was merged into a successor that still holds the quote. +- `reattached`: the node changed, and the quote or the cell's headers now find exactly one place. +- `stale`: nothing is found, so a person must look. + +A `changed-below` result carries a drift, the share of the leaves under the node, counting retired ones, that corrections touched. +Above a quarter the drift is `high`. +The table shows how each anchor resolves at revision 12 ([vectors/resolve.jsonl](../vectors/resolve.jsonl) records them all). + +| Anchor on | Result | Why | +| --- | --- | --- | +| "H$_2$O" in the water sentence | `current` | Nothing in that sentence changed. | +| The cell `1.5260` | `current` | Untouched, though its table changed around it. | +| The water sentence, through the alias `b-p01-text-003` | `current` | The alias leads to the same node. | +| The cell that read `3l0.0` | `stale` | Its text changed and "3l0.0" is no longer in it; a person must look again. | +| "treated as zero" | `reattached` | The sentence changed twice, and the quote occurs in it exactly once, so the anchor is re-pinned. | +| "fitted constants" | `stale` | After the split, those words are in the new sentence `a4jrz2t`, not in `ec5jc93`. | +| "least squares", in the half-sentence `ayea71r` | `moved` | That ID was merged into `xjns57z`, which still holds the quote. | +| The paragraph `ncx2v4f` | `moved` | Merged into `gwzbj3s`, which holds all of its sentences. | +| The running head | `stale` | Deleted, with no successor. | +| The equation | `reattached` | Only its number changed. | +| The figure | `reattached` | Only its label changed, by a `relabel`. | +| The CT–HC cell `1.090` in the garbled row | `reattached` | Its row was deleted, and exactly one cell in Table 1 has the same row and column headers and the same text: the new `b5gd0h1`. | +| Section 2 | `changed-below`, drift high | The section itself is unchanged, and 53% of what it holds or held was touched. | +| Table 1 | `changed-below`, drift high | Rows were replaced and added. | +| The table body | `changed-below`, drift high | 75% of the cells it holds or held were touched. | +| The paragraph whose broken sentence was rejoined | `changed-below`, drift high | Two of the three sentences it has held were touched. | +| The CT–CT row | `changed-below`, drift low | One of its five cells was corrected. | + +A reader shows each note by its result. +A checker of exact words accepts only `current`, `moved` and `reattached`. + +The [W3C Web Annotation Data Model](https://www.w3.org/TR/annotation-model/) is the general W3C Recommendation for annotating web resources. paperspec's annotation layers build on it, with a custom `AnchorSelector` followed by a standard `TextQuoteSelector` as a fallback. +It has no permanent IDs for sentences inside the source, no hashes of the target text, and no results such as `moved` or drift. +See [comparison.md](comparison.md). + +## 6. Review and signatures + +A receipt is a signed record that a person compared a set of nodes with the page. +It lifts a node to F3, the top fidelity level (F0 is one reading; F1, every doubtful place answered; F2, an independent witness agrees) ([spec/08](../spec/08-fidelity.md)). +One signature covers a Merkle tree, a hash over everything reviewed in a sitting, built as in RFC 6962 (a Request for Comments standard; replaced by [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162), which defines the same tree). +The receipts are in [`receipts.jsonl`](../fixtures/packages/hale2026harmonic-damb/receipts.jsonl), and the keys that signed them in [`roster.json`](../fixtures/packages/hale2026harmonic-damb/roster.json). + +- **Before the corrections**, `ana` had signed receipt `npc15pn6675z5` for three cells at revision 0. + Two of them never changed, so the receipt still counts for them. +For the corrected cell it no longer counts, because the cell's hash moved on. +- After the corrections, `ana` signs `y2zw8ctg5s8dp` at F3 for 23 nodes: the cells of Table 1's three data rows (15), its four column headers, the equation, and three sentences (`ec5jc93`, `hca6dc5` and `rr20tev`, the one holding the equation). + `ben` spot-checks it with receipt `mg18668nzxvap`. +His signature, made with his separate spot-check key `ben-spot`, picks 10 nodes nobody could have chosen, and he finds no errors. +- `ana` signs `mvjmb94nz7rdh` for two sentences of section 1, including the new `a4jrz2t`. +- `cara` signs `q465jpwz8afhe` for three sentences on page 2, then revokes it herself (`pcbhtpwvysgq6`) because she had compared them with the crops of another paper. + Those sentences fall back to their earlier levels, which is why `xjns57z` is still F0. +- `ana` signs `gx2s84z9jf9xv` for the figure's three caption sentences. `ben`'s spot-check `yt70fcc3qm0xb` finds a missing period in `caehhp6`, which suspends the receipt until she reviews the sitting again and signs a new one. + +The document's report, in [`document.json`](../fixtures/packages/hale2026harmonic-damb/document.json), counts the result over 45 leaves: 27 at F3, 13 at F2, 4 at F1 and 1 at F0. +The 27 are the 23 nodes of `y2zw8ctg5s8dp`, the 2 of `mvjmb94nz7rdh`, and 2 of the 3 caption sentences. +Those two still count because Ben's spot-check is itself a valid receipt, and he compared them with the page and found them right. +The third, `caehhp6`, stays at F2: a spot-check never raises a node it found in error ([spec/08 §8.2](../spec/08-fidelity.md#82-levels)). + +## 7. Data out of the table + +Table 1 becomes a dataset, `ds-hale-bond-params`, inside the package ([spec/15](../spec/15-datasets.md)). +It is a [Frictionless Data Package](https://datapackage.org/standard/data-package/) with units, uncertainty and an origin added, and the format is `provisional`. +Its CSV keeps every digit as printed (`1.526` and `1.5260` stay different), and every value has an anchor to the cell that prints it, so a claim that rests on a value can show the cell. +The descriptor types the fields as numbers; how a generic Data Package tool treats `1.5260` was not verified. +All twelve value anchors resolve as `current`. +The reference checker, [`tools/check.py`](../tools/check.py), confirms each CSV value equals its cell's text. + +## 8. Sharing without the text + +The team wants to move its notes to another of its own machines without copying the paper there. +[`hale2026harmonic-damb.checks-only`](../fixtures/packages/hale2026harmonic-damb.checks-only/) is the same document with every leaf's text withheld and every hash replaced by an HMAC under the team's key ([spec/12 §12.5](../spec/12-package.md), [spec/05 §5.8](../spec/05-hashes.md)). +An HMAC is a hash mixed with a secret key. +Anyone can recover a plain hash of a short text such as "310.0" by hashing guesses; a keyed hash resists that. +Corrections, receipts, the roster and the dataset are left out too. +IDs, labels, pages and boxes survive, so annotations still land in the right place. +Only someone holding the key and the text can check the values. +The team key suits an export between the team's own machines. +An export to a collaborator outside the team would use a key derived from the pages of the paper instead, so that only someone holding the paper can check it. + +## 9. Recompute, print and query the package + +[The examples](examples.md) show how to recompute one of these hashes with `sha256sum`, print the outline with a few lines of Python, and load the whole package into SQLite to query it. diff --git a/fixtures/README.md b/fixtures/README.md new file mode 100644 index 0000000..d3ebf5b --- /dev/null +++ b/fixtures/README.md @@ -0,0 +1,112 @@ +# Fixtures + +A reader, writer, converter or checker of stored papers needs files to test against, and a newcomer needs examples of what a stored paper looks like. +This folder holds that example data of paperspec (), version 0.1.0. +All text is synthetic, written for these files and dedicated CC0; license fields inside the fixtures describe fictional works. + +Three readers use these files. +A newcomer learns what a stored paper looks like and what can go wrong with one. +An implementer, who writes a reader, writer, converter or checker, tests it against the files. +An expert reviewing the work finds which cases the tests pin and what the published keys do and do not prove. + +Each format here has the status `candidate` or `provisional` in `registry/formats.json`. + +A hash is a fixed-length fingerprint of data: any change to the data changes it. +The hash used here is SHA-256, written in hexadecimal. +A package is one document stored as a folder of files, with a manifest listing every file and its hash. +A node is an addressable part of a document, such as a section, a sentence or a table cell. +A witness is a source file a reading came from, such as a PDF. +A receipt is a signed statement that a named person reviewed listed nodes. + +## Packages + +Each package under `packages/` is a valid document. +A conforming reader accepts each one and recomputes every hash it contains. + +| Package | What it is for | +| --- | --- | +| `packages/hale2026harmonic/` | The main example, followed step by step in [the walkthrough](../docs/walkthrough.md): a chemistry paper that was read once with mistakes and then fixed by twelve corrections. It has a table with two levels of column headers and grouped rows, an equation inside a sentence, a footnote, a figure with text inside its panels and a real image, references, legacy aliases, boxes on fingerprinted pages, receipts in every state (counting, partly invalidated, spot-checked, revoked and suspended), the roster of public keys that checks their signatures, a dataset taken from the table, and derived MathML. | +| `packages/hale2026harmonic.checks-only/` | The same document prepared for sharing within the team: text withheld, every hash an HMAC (a hash computed under a secret key) under the team key. The team key is derived from the team secret in `keys/` ([spec/05](../spec/05-hashes.md), [spec/12 section 12.5](../spec/12-package.md#125-text-policies)). It shows how a team can share its checks on a paywalled paper without sharing the paper. | +| `packages/okafor2025open/` | An open-access paper established from a JATS file (an XML format for journal articles) and a PDF that agree, so every leaf is at fidelity F2, corroborated by an independent witness. | +| `packages/smithlab2027charges/` | A short draft written in Typst (a typesetting language). One of its sentences holds a cross-reference whose target is the address `hale2026harmonic#a4jrz2t`, a sentence of the main example. | +| `packages/tiny2026example/` | A small document, the starting point of the correction vectors (`vectors/corrections.jsonl`) and of every broken package below. | +| `packages/tiny2026example.sct.zip` | The same document as a zipped package, written the way a producer makes a byte-identical archive: entries under one folder named by the key, sorted by path, stored, dated 1980-01-01, with no extra fields ([spec/12 section 12.2](../spec/12-package.md#122-paths)). A reader unpacks it to exactly the folder beside it. | + +## Records + +`records/` holds a valid example of every other format that is a JSON file of its own. +Three formats have their example elsewhere: the stage requirements (`scienting-stages/1`) and the stamp rules (`scienting-stamps/1`) are in [registry/](../registry/README.md), and a bundle (`scienting-bundle/1`) is a SQLite file that `tools/load.py --bundle` builds from the packages. +Each record is a single file, or a folder where a format needs several files. + +| Files | What they are for | +| --- | --- | +| `anchor-span.json`, `anchor-leaf.json`, `anchor-cell.json`, `anchor-paragraph.json` | An anchor is an address pinned to a hash, with a quotation and context, so it can be found again after the text changes. These four anchors point at a span of a sentence, a sentence, a table cell and a paragraph of the main example. | +| `anchor-keyed.json` | An anchor that leaves the team, as in a public layer: its table context is stored as keyed hashes, so the labels cannot be read from it ([spec/06 section 6.3](../spec/06-anchors.md#63-keyed-anchors)). | +| `rights-open.json`, `rights-subscription.json`, `rights-collective.json` | A witness's license and what uses it allows, under an open license, a subscription and a collective license. | +| `policy.json` | A signed team decision that settles a use the rights record leaves unknown. | +| `backend-docling.json`, `backend-examplevendor.json` | The code and weight licenses of a conversion tool and the conditions attached to them. | +| `profile-acme.json`, `profile-smithlab.json` | What those conditions ask about a team: its purpose, its funding and whom it competes with. | +| `roster.json` | The keys that may sign, the role of each key's holder in the team, and what each key may sign. Ana is the owner, so she may revoke anyone's receipt. | +| `layer/` | A layer of annotations on the main example (`layer.json`, `annotations.jsonl`) and the receipt that confirms them (`receipt.json`). | +| `submissions/`, `grades/` | A student's answers to exercises in the layer, and the grader's result for each. | +| `suspect.json` | A doubtful reading raised for review: the converter's reading of an exponent in the main example, before the first correction answered it. | +| `qa-report.json` | Reviewer error bounds for a delivery that covers two of the main example's receipts, signed by the team's owner key. | +| `checklist/` | A conformance checklist (`checklist.json`) for an accessible HTML export of the main example, checked against WCAG 2.1 AA criterion by criterion, and the receipt that covers it at its hash (`receipt.json`). The format is `provisional`. | +| `proof-inclusion.json`, `proof-consistency.json` | Two RFC 9162 proofs: that one node was covered by the main example's first receipt without showing the rest, and that revision 12 of its correction history extends revision 8 rather than rewriting it. | +| `checkpoint.json` | A signed checkpoint of the team's transparency log over the main example's receipts, revocations and roster, as the parsed form of its signed note, cosigned by a witness. The format is `provisional`. | +| `log/` | The same log as the static files a server would publish: `checkpoint` and the hash and entries tiles ([spec/23 §23.4](../spec/23-log.md#234-serving-a-log)). | +| `receipt-ml-dsa.json` | A receipt signed with ML-DSA-65 (FIPS 204) by `dana`, whose roster key is post-quantum. | +| `project.json`, `digitization.json`, `digitization-confirmation.json`, `datasets/`, `view.vl.json`, `snapshot.json`, `draft-ids.jsonl` | A team project; values read off the main example's figure by hand, the receipt that confirms them, and the dataset they yield; a Vega-Lite chart pinned to that dataset; what the draft cites, pinned; and the sentence IDs of the draft's Typst project. These formats are `provisional`. | + +## Broken packages + +Each folder in `invalid/` holds a `package/` folder, or a `package.sct.zip` archive, that breaks exactly one rule, built from `packages/tiny2026example/` by one edit, and an `expect.json` that names the rule. +A conforming implementation refuses every one of them and should report that rule. +`registry/rules.json` lists every rule ID with its meaning, and a validator reports each failure as `path:line: rule: message` ([spec/22 section 22.2](../spec/22-conformance.md#222-validating-a-package)). + +| Case | What is wrong | Rule | +| --- | --- | --- | +| `alias-dangling/` | An alias whose node does not exist. | `doc.id.successor` | +| `bad-id/` | An ID that uses a letter Crockford base32 lacks (i, l, o or u). | `package.schema` | +| `checks-only-plain/` | A checks-only package that still carries text and plain hashes. | `doc.policy.withheld` | +| `cite-not-reference/` | A cite run names a node that is not a reference. | `doc.run.cite` | +| `counts-wrong/` | document.json's counts are not the number of nodes and leaves. | `doc.counts` | +| `crlf/` | A file whose lines end in CR LF, which is not the canonical form. | `package.file.canonical` | +| `empty-optional-file/` | An optional JSONL file with no records. | `package.file.empty` | +| `hash-mismatch/` | A node_hash that does not recompute. | `doc.hash.node-hash` | +| `heading-not-first/` | A heading must be a section's first child. | `doc.tree.child` | +| `history-wrong/` | document.json's history is not the root over the corrections. | `doc.history` | +| `key-suffix/` | A work key whose hash part is not the hash of the work's DOI. | `doc.key.suffix` | +| `key-work/` | A document key whose suffix is not the version's. | `doc.key.work` | +| `location-unknown-page/` | A location on a page no witness has. | `doc.location.page` | +| `manifest-hash/` | A file changed after the manifest was written. | `package.manifest.hash` | +| `manifest-key/` | The manifest names another key than document.json. | `package.manifest.key` | +| `missing-required-file/` | A required file is missing. | `package.file.required` | +| `not-canonical/` | A line that is valid JSON but not canonical JSON (the fixed form of RFC 8785, which gives equal data identical bytes). | `package.file.canonical` | +| `receipt-root/` | A receipt whose Merkle root (one hash that summarizes a list of hashes) does not recompute. | `doc.receipt.root` | +| `receipt-signature/` | A receipt changed after it was signed. | `doc.receipt.signature` | +| `receipt-unsorted-nodes/` | A receipt whose nodes are not sorted by ID. | `doc.receipt.nodes` | +| `retired-live/` | An ID that is both live and retired. | `doc.id.retired-live` | +| `rev-without-corrections/` | document.json's rev is not the number of corrections. | `doc.correction.rev` | +| `root-mismatch/` | document.json's root is not the root node's node_hash. | `doc.hash.root` | +| `signer-mismatch/` | A receipt whose signature was made with another key than the signer it names. | `doc.receipt.signature` | +| `style-sup-sub/` | A run cannot be both a subscript and a superscript. | `doc.run.style` | +| `text-edited/` | Text changed without its hashes. | `doc.hash.text-hash` | +| `unknown-kind/` | Kinds outside the list are refused. | `package.schema` | +| `unlisted-file/` | A file the manifest does not list. | `package.manifest.unlisted` | +| `unsafe-path/` | The manifest lists a path that leaves the package. | `package.path.unsafe` | +| `zip-symlink/` | A zipped package with an entry that is a symbolic link. | `package.zip.entry` | +| `zip-traversal/` | A zipped package with an entry whose path leaves the package folder. | `package.zip.entry` | + +## Keys + +`keys/` holds the Ed25519 secret keys (`ana`, `ben`, `cara`, `wit`, the witness, and `ben-spot`, whose VRF proof picks the nodes of a spot-check), the seed of `dana`'s ML-DSA-65 key, which signed the fixtures' receipts, and the team secret of the checks-only package. +Ed25519 is a signature scheme: the secret key makes a signature, and the public key in a roster verifies it. +These are published test keys. +Anyone can reproduce the signatures, so a signature made with these keys proves nothing about who made it. +Use them for nothing else. + +## Sources + +`src/` holds the hand-written descriptions of the three main documents, as first read; see [src/README.md](src/README.md). +Everything else here is generated by `python3 tools/build.py`, so change the sources or the builder, never the generated files. diff --git a/fixtures/invalid/alias-dangling/expect.json b/fixtures/invalid/alias-dangling/expect.json new file mode 100644 index 0000000..e340326 --- /dev/null +++ b/fixtures/invalid/alias-dangling/expect.json @@ -0,0 +1 @@ +{"note":"An alias whose node does not exist.","rule":"doc.id.successor"} diff --git a/fixtures/invalid/alias-dangling/package/MANIFEST.json b/fixtures/invalid/alias-dangling/package/MANIFEST.json new file mode 100644 index 0000000..8562071 --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"ids.jsonl","sha256":"1eb53589cd394214dd4ee15be98a3dfbacec5e585a1e655fe2dfeff71a07e19e","size":61},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/alias-dangling/package/document.json b/fixtures/invalid/alias-dangling/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/alias-dangling/package/ids.jsonl b/fixtures/invalid/alias-dangling/package/ids.jsonl new file mode 100644 index 0000000..e3e686e --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/ids.jsonl @@ -0,0 +1 @@ +{"id":"b-p01-text-001","kind":"alias","successor":"zzzzzzz"} diff --git a/fixtures/invalid/alias-dangling/package/nodes.jsonl b/fixtures/invalid/alias-dangling/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/alias-dangling/package/provenance.json b/fixtures/invalid/alias-dangling/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/alias-dangling/package/receipts.jsonl b/fixtures/invalid/alias-dangling/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/alias-dangling/package/references.jsonl b/fixtures/invalid/alias-dangling/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/alias-dangling/package/roster.json b/fixtures/invalid/alias-dangling/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key:z4xcFfnTC6XJy4gzg9whfyMzcnxV7yM2XafMFynKXhAEvMgjfQCxSnjZaa53arz2iNo8v35ZN5SdAUcbFkbuvftcMczRT2CPhYsXkNYZhDzXWQVS5KZZkhnMDmwChWfgRHu4Bs6KHyEmvzwesTioW5yS3YtfR7mUPJAwWSRq9f23HRxzenGpVVBcVjpd8YDZ4Y1ZamcUfesnB6pGLrPtLDvGM7Te1cJWoRG4m3TetEF3i9V3W4CH43nouCwUPbjy7dpTNEWiCqaTPiPhV8UEWBD8b9e1729PwoUFyAFreuq6wvhphLKGHhFCFujrUtqDZPs6FFF1Q7Lpt9eFcjbxrZSAYsh9VTfxaUeQ4HmFqzrg28EEjJzxxADZyjTXDsfwskRbibHSms9bbN2xK6GQcUxE2mrA2ULfYwsk5RQsVULUTj3pMMXpxRqP4zerzui2ZRZ3SqeNUwqnhmF861pEtcemZPY6ivcX41QK3ekCtpc1HndtY9xua1Lrhs4jd6qEbxHWzBPHok6qTpyxnn7ubZssBqSMz3uNrou1ayZGDn1ayAXtzCJPjAcxdNX1dpm5vyDB8GYtNKsQHuiX5xUd2EMAVfq4cFrZ6ncY1zrG5exH6mhJYbZfW7BgXxq7GsnzAAGkzgHCRADe5EEm1Hj1YdmVBTiaGsPGYkF4Mcrw3T2j3AcPJCzPLRNjKBKXyHAcf3VPUmreaHd1GoA5zqvtANSPmppY2AhCAj8u6n92fiyBgrvJTh4hyvtMFcwaa9vKnY9rBS4n5XGpdwKQe11Tk5sah8VZc2PyH2WPBU3DmhZSwUkKHRQQQQMXjrLjuMtygzxWBgrJAcWRPzxmzHZEj5x9GgFZb4dPDwqVXsgR25KrpuyQKcxfbxzQoRprnhu1ec8SfX5zeUo282Si9dBZ3JVdxzYHzP6xSiuBeHHFMvMwb1MKUq2dMi9vWdg2eCDo5wTvSaTVcdYGtZsT7HMswWtxx9GLw1RafYRcNqMhBhCbRdJszUKjQKwNNZbaryRs4kTYicuE24PWbqfxdJnrzrLbXnVBDMNHjX8ESXSKTMnAoE1AiLgjdj3zbBrY39Pxc72EikA7GvP2qxKZBkJ6G2RRWCw9d3nZKmTmQqP5PP9HgdtSTnZhNTJqBkwL3iqfoWxtbkLjLLSQc3dbFpmhe4kAh7VUUDcLzjb4nGzCbr5U1YoqAoLnSC9BPijnfMHxBP6i8cR762ryxPwe7HdGk62DVYoqxbwz8ygrDPjdPi3t11PpHp51GxuhMkoR3GFxAdMEv8j4tVpJ6qjefULEFTtRPzZ5kTE57RTxC4wg62qcYwupWx4dvvB2BR9ZGnNwCojpBYByeeYETrgm4HJjjS3SH64sbpyqz7336YMAcWyQFc9BeqjQHHUHS8CJ82N88apbPPE8N9X76DQ8PgwACtR4D5ofE9o14kpdVZFV2YMtmnKCybNLn3atspK6T1ZPYB3vQ1c4DbzZFgCpm6izEzxsY17in79ieo3cY965Cr5mkxca29VxcTaEtovdu9sKAL4VgCZzWkps5nnimX5JBEdVKYxTtMb6CcTkdWGFtXBTBuAMTpRNLXG5nG4bq9XXLkFS4oXpVS7KayqAMtrrqttpgwdAPNuzd6E4JskxdenwMq6qzMTDKoMqGDVEKkwCxCcbUtNpHGMLWMMk9MDrsPvcU8u2C89UmJmsfS5gQqswkz6TfXvthM3wPcuKaX7TUJJRzYstWsXRKUaPqqT3ppftCbXPFgia3mXkA5bk9Y3GWcTADGTnzKkTzbnL6hsgQW1FyvsFwUiWUJd5weeHkfaHt8iV3PKy99S6d831iLCfFWM6bYZgEBvyx5seHSpiaXRfSv4A2yDsf4Tb4EVsyDUJPUmZLnbFkJmw46A6PoQHdwfBbXWV47DFM6w5mKXCPmKzuAG1Vmw7D36n4oHd91r1VzTynVnhD1EA5UVh4qhiw2CnWgo2uAPxEpLYnvrCLiVprnzdPzvZZqMUxXRFWHwfshJDARRLvP933693aWxa5PeDNgMjZYgKJBV5e66Z1Mk5rYegEuSq7uyz8Mw3iuidtJeqBugbNCYeNdmeBPgKux8HcuFNqQaVwhP9vW8vyaU7DvuKEeXs1uyAgtk9RCua2Mx8rQqUwQigWNjXaJoSYqMT9SVEGUSYAGQiLnMFENqG1r87uhxV58hTwR8QED9cQkStFXeuZAMY6FWTZCsD5juC48KdqoUQYr77iBy7fW2quQNdPvwEUdhh1mzSTX2PPubCbm9rcdBxBQ2CBZizn1EsbPMic1X39t17scRE5F4Yank18EF4aUmJwwNHx5m1WKDQMZ1kJQRyhtRvAHTPqBdJCw5SHaEqBVpEQHUZwBKsQoTRj4Gk1opv6XfczoK3MLuprTMSx2maw5Gv6LhF2SWUvEXMMqoeqVzyP9g11dumkKQLMiAQa2VGaa7EF7Foj2ZDUhPM6PPiffHMhDMwWhRBywg3SC6aP9zz2TdMXweHv8rags9chFZ217aAP3bcCf5i1VZqPT9b8Ea7ykjjUy6PNwiSforRXN46suuRFREuhx6DuWDojythjH73wMAeKKx23rF4QfdUxzkC2mmmS4dq8Xx7Bda4e31EGab4t81Jk4dAVGjSrZC9wx89CAjovhoejgDTKNsN3ri4GjW9UD","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/alias-dangling/package/witnesses.json b/fixtures/invalid/alias-dangling/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/alias-dangling/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/bad-id/expect.json b/fixtures/invalid/bad-id/expect.json new file mode 100644 index 0000000..38fe4be --- /dev/null +++ b/fixtures/invalid/bad-id/expect.json @@ -0,0 +1 @@ +{"note":"IDs use Crockford base32, which has no i, l, o or u.","rule":"package.schema"} diff --git a/fixtures/invalid/bad-id/package/MANIFEST.json b/fixtures/invalid/bad-id/package/MANIFEST.json new file mode 100644 index 0000000..093d72a --- /dev/null +++ b/fixtures/invalid/bad-id/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"fd0cf6999bcce9c09cd7fb3aa0e1183bbbccf4c1ca0236e62c63a164e8dbc7f1","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/bad-id/package/document.json b/fixtures/invalid/bad-id/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/bad-id/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/bad-id/package/nodes.jsonl b/fixtures/invalid/bad-id/package/nodes.jsonl new file mode 100644 index 0000000..9518c0d --- /dev/null +++ b/fixtures/invalid/bad-id/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"i1lo0uu","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/bad-id/package/provenance.json b/fixtures/invalid/bad-id/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/bad-id/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/bad-id/package/receipts.jsonl b/fixtures/invalid/bad-id/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/bad-id/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/bad-id/package/references.jsonl b/fixtures/invalid/bad-id/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/bad-id/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/bad-id/package/roster.json b/fixtures/invalid/bad-id/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/bad-id/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/bad-id/package/witnesses.json b/fixtures/invalid/bad-id/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/bad-id/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/checks-only-plain/expect.json b/fixtures/invalid/checks-only-plain/expect.json new file mode 100644 index 0000000..c711e41 --- /dev/null +++ b/fixtures/invalid/checks-only-plain/expect.json @@ -0,0 +1 @@ +{"note":"A checks-only package that still carries text and plain hashes.","rule":"doc.policy.withheld"} diff --git a/fixtures/invalid/checks-only-plain/package/MANIFEST.json b/fixtures/invalid/checks-only-plain/package/MANIFEST.json new file mode 100644 index 0000000..0932a9a --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"a7e83339ea04205a7b1f425299450bca661586a93ac7d959ceb60fb3c68207dd","size":771},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/checks-only-plain/package/document.json b/fixtures/invalid/checks-only-plain/package/document.json new file mode 100644 index 0000000..15f7ccd --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"checks-only","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/checks-only-plain/package/nodes.jsonl b/fixtures/invalid/checks-only-plain/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/checks-only-plain/package/provenance.json b/fixtures/invalid/checks-only-plain/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/checks-only-plain/package/receipts.jsonl b/fixtures/invalid/checks-only-plain/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/checks-only-plain/package/references.jsonl b/fixtures/invalid/checks-only-plain/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/checks-only-plain/package/roster.json b/fixtures/invalid/checks-only-plain/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/checks-only-plain/package/witnesses.json b/fixtures/invalid/checks-only-plain/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/checks-only-plain/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/cite-not-reference/expect.json b/fixtures/invalid/cite-not-reference/expect.json new file mode 100644 index 0000000..a4591fa --- /dev/null +++ b/fixtures/invalid/cite-not-reference/expect.json @@ -0,0 +1 @@ +{"note":"A cite run names a node that is not a reference.","rule":"doc.run.cite"} diff --git a/fixtures/invalid/cite-not-reference/package/MANIFEST.json b/fixtures/invalid/cite-not-reference/package/MANIFEST.json new file mode 100644 index 0000000..f552500 --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"d31b7bda29230dee3a57a1965419ca2133ad6035ca6eb7c94968c652d4c660c3","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/cite-not-reference/package/document.json b/fixtures/invalid/cite-not-reference/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/cite-not-reference/package/nodes.jsonl b/fixtures/invalid/cite-not-reference/package/nodes.jsonl new file mode 100644 index 0000000..7a8467a --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["jvnys4s"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/cite-not-reference/package/provenance.json b/fixtures/invalid/cite-not-reference/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/cite-not-reference/package/receipts.jsonl b/fixtures/invalid/cite-not-reference/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/cite-not-reference/package/references.jsonl b/fixtures/invalid/cite-not-reference/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/cite-not-reference/package/roster.json b/fixtures/invalid/cite-not-reference/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/cite-not-reference/package/witnesses.json b/fixtures/invalid/cite-not-reference/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/cite-not-reference/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/counts-wrong/expect.json b/fixtures/invalid/counts-wrong/expect.json new file mode 100644 index 0000000..e95edfe --- /dev/null +++ b/fixtures/invalid/counts-wrong/expect.json @@ -0,0 +1 @@ +{"note":"document.json's counts are not the number of nodes and leaves.","rule":"doc.counts"} diff --git a/fixtures/invalid/counts-wrong/package/MANIFEST.json b/fixtures/invalid/counts-wrong/package/MANIFEST.json new file mode 100644 index 0000000..4b4e810 --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"4dda6a318c14ce1817ca3837950777100570c1fb0088a5d000d068d1912a0fdb","size":762},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/counts-wrong/package/document.json b/fixtures/invalid/counts-wrong/package/document.json new file mode 100644 index 0000000..6bec509 --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":1,"nodes":1},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/counts-wrong/package/nodes.jsonl b/fixtures/invalid/counts-wrong/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/counts-wrong/package/provenance.json b/fixtures/invalid/counts-wrong/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/counts-wrong/package/receipts.jsonl b/fixtures/invalid/counts-wrong/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/counts-wrong/package/references.jsonl b/fixtures/invalid/counts-wrong/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/counts-wrong/package/roster.json b/fixtures/invalid/counts-wrong/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/counts-wrong/package/witnesses.json b/fixtures/invalid/counts-wrong/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/counts-wrong/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/crlf/expect.json b/fixtures/invalid/crlf/expect.json new file mode 100644 index 0000000..6beecd3 --- /dev/null +++ b/fixtures/invalid/crlf/expect.json @@ -0,0 +1 @@ +{"note":"A file whose lines end in CR LF, which is not the canonical form.","rule":"package.file.canonical"} diff --git a/fixtures/invalid/crlf/package/MANIFEST.json b/fixtures/invalid/crlf/package/MANIFEST.json new file mode 100644 index 0000000..3812ba9 --- /dev/null +++ b/fixtures/invalid/crlf/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"fcbae067529e8476e0fbace4ed94cbb174c31b943fb4f26dc63b316f5dc46b9c","size":227},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/crlf/package/document.json b/fixtures/invalid/crlf/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/crlf/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/crlf/package/nodes.jsonl b/fixtures/invalid/crlf/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/crlf/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/crlf/package/provenance.json b/fixtures/invalid/crlf/package/provenance.json new file mode 100644 index 0000000..58e43f4 --- /dev/null +++ b/fixtures/invalid/crlf/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/crlf/package/receipts.jsonl b/fixtures/invalid/crlf/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/crlf/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/crlf/package/references.jsonl b/fixtures/invalid/crlf/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/crlf/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/crlf/package/roster.json b/fixtures/invalid/crlf/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/crlf/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/crlf/package/witnesses.json b/fixtures/invalid/crlf/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/crlf/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/empty-optional-file/expect.json b/fixtures/invalid/empty-optional-file/expect.json new file mode 100644 index 0000000..5815596 --- /dev/null +++ b/fixtures/invalid/empty-optional-file/expect.json @@ -0,0 +1 @@ +{"note":"An optional JSONL file with no records.","rule":"package.file.empty"} diff --git a/fixtures/invalid/empty-optional-file/package/MANIFEST.json b/fixtures/invalid/empty-optional-file/package/MANIFEST.json new file mode 100644 index 0000000..a7b5e74 --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"suspects.jsonl","sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","size":0},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/empty-optional-file/package/document.json b/fixtures/invalid/empty-optional-file/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/empty-optional-file/package/nodes.jsonl b/fixtures/invalid/empty-optional-file/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/empty-optional-file/package/provenance.json b/fixtures/invalid/empty-optional-file/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/empty-optional-file/package/receipts.jsonl b/fixtures/invalid/empty-optional-file/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/empty-optional-file/package/references.jsonl b/fixtures/invalid/empty-optional-file/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/empty-optional-file/package/roster.json b/fixtures/invalid/empty-optional-file/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/empty-optional-file/package/suspects.jsonl b/fixtures/invalid/empty-optional-file/package/suspects.jsonl new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/invalid/empty-optional-file/package/witnesses.json b/fixtures/invalid/empty-optional-file/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/empty-optional-file/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/hash-mismatch/expect.json b/fixtures/invalid/hash-mismatch/expect.json new file mode 100644 index 0000000..b0c19e7 --- /dev/null +++ b/fixtures/invalid/hash-mismatch/expect.json @@ -0,0 +1 @@ +{"note":"A node_hash that does not recompute.","rule":"doc.hash.node-hash"} diff --git a/fixtures/invalid/hash-mismatch/package/MANIFEST.json b/fixtures/invalid/hash-mismatch/package/MANIFEST.json new file mode 100644 index 0000000..f4aa34a --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"11e236bf3394043f2b42090a9149fa598fa1e3c5e947df063b38f569b2d27fa2","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/hash-mismatch/package/document.json b/fixtures/invalid/hash-mismatch/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/hash-mismatch/package/nodes.jsonl b/fixtures/invalid/hash-mismatch/package/nodes.jsonl new file mode 100644 index 0000000..790cf32 --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"0000000000000000000000000000000000000000000000000000000000000000","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/hash-mismatch/package/provenance.json b/fixtures/invalid/hash-mismatch/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/hash-mismatch/package/receipts.jsonl b/fixtures/invalid/hash-mismatch/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/hash-mismatch/package/references.jsonl b/fixtures/invalid/hash-mismatch/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/hash-mismatch/package/roster.json b/fixtures/invalid/hash-mismatch/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/hash-mismatch/package/witnesses.json b/fixtures/invalid/hash-mismatch/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/hash-mismatch/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/heading-not-first/expect.json b/fixtures/invalid/heading-not-first/expect.json new file mode 100644 index 0000000..6a5d550 --- /dev/null +++ b/fixtures/invalid/heading-not-first/expect.json @@ -0,0 +1 @@ +{"note":"A heading must be a section's first child.","rule":"doc.tree.child"} diff --git a/fixtures/invalid/heading-not-first/package/MANIFEST.json b/fixtures/invalid/heading-not-first/package/MANIFEST.json new file mode 100644 index 0000000..7c7f7b2 --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"aae6d3db59616ae07b7521936e0e92fef6555bfc157eaeff231ebbd6d1621a81","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/heading-not-first/package/document.json b/fixtures/invalid/heading-not-first/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/heading-not-first/package/nodes.jsonl b/fixtures/invalid/heading-not-first/package/nodes.jsonl new file mode 100644 index 0000000..954b8ba --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":0,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":1,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/heading-not-first/package/provenance.json b/fixtures/invalid/heading-not-first/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/heading-not-first/package/receipts.jsonl b/fixtures/invalid/heading-not-first/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/heading-not-first/package/references.jsonl b/fixtures/invalid/heading-not-first/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/heading-not-first/package/roster.json b/fixtures/invalid/heading-not-first/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key:z4xcFfnTC6XJy4gzg9whfyMzcnxV7yM2XafMFynKXhAEvMgjfQCxSnjZaa53arz2iNo8v35ZN5SdAUcbFkbuvftcMczRT2CPhYsXkNYZhDzXWQVS5KZZkhnMDmwChWfgRHu4Bs6KHyEmvzwesTioW5yS3YtfR7mUPJAwWSRq9f23HRxzenGpVVBcVjpd8YDZ4Y1ZamcUfesnB6pGLrPtLDvGM7Te1cJWoRG4m3TetEF3i9V3W4CH43nouCwUPbjy7dpTNEWiCqaTPiPhV8UEWBD8b9e1729PwoUFyAFreuq6wvhphLKGHhFCFujrUtqDZPs6FFF1Q7Lpt9eFcjbxrZSAYsh9VTfxaUeQ4HmFqzrg28EEjJzxxADZyjTXDsfwskRbibHSms9bbN2xK6GQcUxE2mrA2ULfYwsk5RQsVULUTj3pMMXpxRqP4zerzui2ZRZ3SqeNUwqnhmF861pEtcemZPY6ivcX41QK3ekCtpc1HndtY9xua1Lrhs4jd6qEbxHWzBPHok6qTpyxnn7ubZssBqSMz3uNrou1ayZGDn1ayAXtzCJPjAcxdNX1dpm5vyDB8GYtNKsQHuiX5xUd2EMAVfq4cFrZ6ncY1zrG5exH6mhJYbZfW7BgXxq7GsnzAAGkzgHCRADe5EEm1Hj1YdmVBTiaGsPGYkF4Mcrw3T2j3AcPJCzPLRNjKBKXyHAcf3VPUmreaHd1GoA5zqvtANSPmppY2AhCAj8u6n92fiyBgrvJTh4hyvtMFcwaa9vKnY9rBS4n5XGpdwKQe11Tk5sah8VZc2PyH2WPBU3DmhZSwUkKHRQQQQMXjrLjuMtygzxWBgrJAcWRPzxmzHZEj5x9GgFZb4dPDwqVXsgR25KrpuyQKcxfbxzQoRprnhu1ec8SfX5zeUo282Si9dBZ3JVdxzYHzP6xSiuBeHHFMvMwb1MKUq2dMi9vWdg2eCDo5wTvSaTVcdYGtZsT7HMswWtxx9GLw1RafYRcNqMhBhCbRdJszUKjQKwNNZbaryRs4kTYicuE24PWbqfxdJnrzrLbXnVBDMNHjX8ESXSKTMnAoE1AiLgjdj3zbBrY39Pxc72EikA7GvP2qxKZBkJ6G2RRWCw9d3nZKmTmQqP5PP9HgdtSTnZhNTJqBkwL3iqfoWxtbkLjLLSQc3dbFpmhe4kAh7VUUDcLzjb4nGzCbr5U1YoqAoLnSC9BPijnfMHxBP6i8cR762ryxPwe7HdGk62DVYoqxbwz8ygrDPjdPi3t11PpHp51GxuhMkoR3GFxAdMEv8j4tVpJ6qjefULEFTtRPzZ5kTE57RTxC4wg62qcYwupWx4dvvB2BR9ZGnNwCojpBYByeeYETrgm4HJjjS3SH64sbpyqz7336YMAcWyQFc9BeqjQHHUHS8CJ82N88apbPPE8N9X76DQ8PgwACtR4D5ofE9o14kpdVZFV2YMtmnKCybNLn3atspK6T1ZPYB3vQ1c4DbzZFgCpm6izEzxsY17in79ieo3cY965Cr5mkxca29VxcTaEtovdu9sKAL4VgCZzWkps5nnimX5JBEdVKYxTtMb6CcTkdWGFtXBTBuAMTpRNLXG5nG4bq9XXLkFS4oXpVS7KayqAMtrrqttpgwdAPNuzd6E4JskxdenwMq6qzMTDKoMqGDVEKkwCxCcbUtNpHGMLWMMk9MDrsPvcU8u2C89UmJmsfS5gQqswkz6TfXvthM3wPcuKaX7TUJJRzYstWsXRKUaPqqT3ppftCbXPFgia3mXkA5bk9Y3GWcTADGTnzKkTzbnL6hsgQW1FyvsFwUiWUJd5weeHkfaHt8iV3PKy99S6d831iLCfFWM6bYZgEBvyx5seHSpiaXRfSv4A2yDsf4Tb4EVsyDUJPUmZLnbFkJmw46A6PoQHdwfBbXWV47DFM6w5mKXCPmKzuAG1Vmw7D36n4oHd91r1VzTynVnhD1EA5UVh4qhiw2CnWgo2uAPxEpLYnvrCLiVprnzdPzvZZqMUxXRFWHwfshJDARRLvP933693aWxa5PeDNgMjZYgKJBV5e66Z1Mk5rYegEuSq7uyz8Mw3iuidtJeqBugbNCYeNdmeBPgKux8HcuFNqQaVwhP9vW8vyaU7DvuKEeXs1uyAgtk9RCua2Mx8rQqUwQigWNjXaJoSYqMT9SVEGUSYAGQiLnMFENqG1r87uhxV58hTwR8QED9cQkStFXeuZAMY6FWTZCsD5juC48KdqoUQYr77iBy7fW2quQNdPvwEUdhh1mzSTX2PPubCbm9rcdBxBQ2CBZizn1EsbPMic1X39t17scRE5F4Yank18EF4aUmJwwNHx5m1WKDQMZ1kJQRyhtRvAHTPqBdJCw5SHaEqBVpEQHUZwBKsQoTRj4Gk1opv6XfczoK3MLuprTMSx2maw5Gv6LhF2SWUvEXMMqoeqVzyP9g11dumkKQLMiAQa2VGaa7EF7Foj2ZDUhPM6PPiffHMhDMwWhRBywg3SC6aP9zz2TdMXweHv8rags9chFZ217aAP3bcCf5i1VZqPT9b8Ea7ykjjUy6PNwiSforRXN46suuRFREuhx6DuWDojythjH73wMAeKKx23rF4QfdUxzkC2mmmS4dq8Xx7Bda4e31EGab4t81Jk4dAVGjSrZC9wx89CAjovhoejgDTKNsN3ri4GjW9UD","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/heading-not-first/package/witnesses.json b/fixtures/invalid/heading-not-first/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/heading-not-first/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/history-wrong/expect.json b/fixtures/invalid/history-wrong/expect.json new file mode 100644 index 0000000..0e64c53 --- /dev/null +++ b/fixtures/invalid/history-wrong/expect.json @@ -0,0 +1 @@ +{"note":"document.json's history is not the root over the corrections.","rule":"doc.history"} diff --git a/fixtures/invalid/history-wrong/package/MANIFEST.json b/fixtures/invalid/history-wrong/package/MANIFEST.json new file mode 100644 index 0000000..bef6fd7 --- /dev/null +++ b/fixtures/invalid/history-wrong/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"8531f4c3fd2b551358b320a9da2889c7e21c89db51fdb136d5927e49c707136b","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/history-wrong/package/document.json b/fixtures/invalid/history-wrong/package/document.json new file mode 100644 index 0000000..b5a6727 --- /dev/null +++ b/fixtures/invalid/history-wrong/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"4444444444444444444444444444444444444444444444444444444444444444","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/history-wrong/package/nodes.jsonl b/fixtures/invalid/history-wrong/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/history-wrong/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/history-wrong/package/provenance.json b/fixtures/invalid/history-wrong/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/history-wrong/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/history-wrong/package/receipts.jsonl b/fixtures/invalid/history-wrong/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/history-wrong/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/history-wrong/package/references.jsonl b/fixtures/invalid/history-wrong/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/history-wrong/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/history-wrong/package/roster.json b/fixtures/invalid/history-wrong/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/history-wrong/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/history-wrong/package/witnesses.json b/fixtures/invalid/history-wrong/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/history-wrong/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/key-suffix/expect.json b/fixtures/invalid/key-suffix/expect.json new file mode 100644 index 0000000..187f511 --- /dev/null +++ b/fixtures/invalid/key-suffix/expect.json @@ -0,0 +1 @@ +{"note":"A work key whose hash part is not the hash of the work's DOI.","rule":"doc.key.suffix"} diff --git a/fixtures/invalid/key-suffix/package/MANIFEST.json b/fixtures/invalid/key-suffix/package/MANIFEST.json new file mode 100644 index 0000000..f35a1d9 --- /dev/null +++ b/fixtures/invalid/key-suffix/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"50d2b2546a62f007512304d578b6fa65adc0f3b643d91a03940b5d6c9b652b7d","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-zzzz"} diff --git a/fixtures/invalid/key-suffix/package/document.json b/fixtures/invalid/key-suffix/package/document.json new file mode 100644 index 0000000..e825e0e --- /dev/null +++ b/fixtures/invalid/key-suffix/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-zzzz","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-zzzz","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/key-suffix/package/nodes.jsonl b/fixtures/invalid/key-suffix/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/key-suffix/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/key-suffix/package/provenance.json b/fixtures/invalid/key-suffix/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/key-suffix/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/key-suffix/package/receipts.jsonl b/fixtures/invalid/key-suffix/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/key-suffix/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/key-suffix/package/references.jsonl b/fixtures/invalid/key-suffix/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/key-suffix/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/key-suffix/package/roster.json b/fixtures/invalid/key-suffix/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/key-suffix/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/key-suffix/package/witnesses.json b/fixtures/invalid/key-suffix/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/key-suffix/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/key-work/expect.json b/fixtures/invalid/key-work/expect.json new file mode 100644 index 0000000..5b1b86d --- /dev/null +++ b/fixtures/invalid/key-work/expect.json @@ -0,0 +1 @@ +{"note":"A document key whose suffix is not the version's.","rule":"doc.key.work"} diff --git a/fixtures/invalid/key-work/package/MANIFEST.json b/fixtures/invalid/key-work/package/MANIFEST.json new file mode 100644 index 0000000..6cb4223 --- /dev/null +++ b/fixtures/invalid/key-work/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"f457aad130c7c493be70df8dfbd85f9de3eb41d30ed2ce1504aaad1d1ccb291d","size":767},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm.si"} diff --git a/fixtures/invalid/key-work/package/document.json b/fixtures/invalid/key-work/package/document.json new file mode 100644 index 0000000..2ed48a7 --- /dev/null +++ b/fixtures/invalid/key-work/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm.si","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/key-work/package/nodes.jsonl b/fixtures/invalid/key-work/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/key-work/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/key-work/package/provenance.json b/fixtures/invalid/key-work/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/key-work/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/key-work/package/receipts.jsonl b/fixtures/invalid/key-work/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/key-work/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/key-work/package/references.jsonl b/fixtures/invalid/key-work/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/key-work/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/key-work/package/roster.json b/fixtures/invalid/key-work/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/key-work/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/key-work/package/witnesses.json b/fixtures/invalid/key-work/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/key-work/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/location-unknown-page/expect.json b/fixtures/invalid/location-unknown-page/expect.json new file mode 100644 index 0000000..0248fcc --- /dev/null +++ b/fixtures/invalid/location-unknown-page/expect.json @@ -0,0 +1 @@ +{"note":"A location on a page no witness has.","rule":"doc.location.page"} diff --git a/fixtures/invalid/location-unknown-page/package/MANIFEST.json b/fixtures/invalid/location-unknown-page/package/MANIFEST.json new file mode 100644 index 0000000..25b50a6 --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"locations.jsonl","sha256":"f9b30f0b834ea3846e1a01032495fcca1857cfe341a91b2e9bea4a7bdc7fdf5f","size":130},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/location-unknown-page/package/document.json b/fixtures/invalid/location-unknown-page/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/location-unknown-page/package/locations.jsonl b/fixtures/invalid/location-unknown-page/package/locations.jsonl new file mode 100644 index 0000000..0c95cb6 --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/locations.jsonl @@ -0,0 +1 @@ +{"boxes":[[72,72,200,84]],"node":"jvnys4s","page":1,"page_fp":"3333333333333333333333333333333333333333333333333333333333333333"} diff --git a/fixtures/invalid/location-unknown-page/package/nodes.jsonl b/fixtures/invalid/location-unknown-page/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/location-unknown-page/package/provenance.json b/fixtures/invalid/location-unknown-page/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/location-unknown-page/package/receipts.jsonl b/fixtures/invalid/location-unknown-page/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/location-unknown-page/package/references.jsonl b/fixtures/invalid/location-unknown-page/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/location-unknown-page/package/roster.json b/fixtures/invalid/location-unknown-page/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/location-unknown-page/package/witnesses.json b/fixtures/invalid/location-unknown-page/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/location-unknown-page/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/manifest-hash/expect.json b/fixtures/invalid/manifest-hash/expect.json new file mode 100644 index 0000000..aa3fff2 --- /dev/null +++ b/fixtures/invalid/manifest-hash/expect.json @@ -0,0 +1 @@ +{"note":"A file changed after the manifest was written.","rule":"package.manifest.hash"} diff --git a/fixtures/invalid/manifest-hash/package/MANIFEST.json b/fixtures/invalid/manifest-hash/package/MANIFEST.json new file mode 100644 index 0000000..6be6656 --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/manifest-hash/package/document.json b/fixtures/invalid/manifest-hash/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/manifest-hash/package/nodes.jsonl b/fixtures/invalid/manifest-hash/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/manifest-hash/package/provenance.json b/fixtures/invalid/manifest-hash/package/provenance.json new file mode 100644 index 0000000..e23c307 --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/provenance.json @@ -0,0 +1,2 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} + \ No newline at end of file diff --git a/fixtures/invalid/manifest-hash/package/receipts.jsonl b/fixtures/invalid/manifest-hash/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/manifest-hash/package/references.jsonl b/fixtures/invalid/manifest-hash/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/manifest-hash/package/roster.json b/fixtures/invalid/manifest-hash/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/manifest-hash/package/witnesses.json b/fixtures/invalid/manifest-hash/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/manifest-hash/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/manifest-key/expect.json b/fixtures/invalid/manifest-key/expect.json new file mode 100644 index 0000000..780e5dc --- /dev/null +++ b/fixtures/invalid/manifest-key/expect.json @@ -0,0 +1 @@ +{"note":"The manifest names another key than document.json.","rule":"package.manifest.key"} diff --git a/fixtures/invalid/manifest-key/package/MANIFEST.json b/fixtures/invalid/manifest-key/package/MANIFEST.json new file mode 100644 index 0000000..c946d80 --- /dev/null +++ b/fixtures/invalid/manifest-key/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"other2026example-0000"} diff --git a/fixtures/invalid/manifest-key/package/document.json b/fixtures/invalid/manifest-key/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/manifest-key/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/manifest-key/package/nodes.jsonl b/fixtures/invalid/manifest-key/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/manifest-key/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/manifest-key/package/provenance.json b/fixtures/invalid/manifest-key/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/manifest-key/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/manifest-key/package/receipts.jsonl b/fixtures/invalid/manifest-key/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/manifest-key/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/manifest-key/package/references.jsonl b/fixtures/invalid/manifest-key/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/manifest-key/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/manifest-key/package/roster.json b/fixtures/invalid/manifest-key/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/manifest-key/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key:z4xcFfnTC6XJy4gzg9whfyMzcnxV7yM2XafMFynKXhAEvMgjfQCxSnjZaa53arz2iNo8v35ZN5SdAUcbFkbuvftcMczRT2CPhYsXkNYZhDzXWQVS5KZZkhnMDmwChWfgRHu4Bs6KHyEmvzwesTioW5yS3YtfR7mUPJAwWSRq9f23HRxzenGpVVBcVjpd8YDZ4Y1ZamcUfesnB6pGLrPtLDvGM7Te1cJWoRG4m3TetEF3i9V3W4CH43nouCwUPbjy7dpTNEWiCqaTPiPhV8UEWBD8b9e1729PwoUFyAFreuq6wvhphLKGHhFCFujrUtqDZPs6FFF1Q7Lpt9eFcjbxrZSAYsh9VTfxaUeQ4HmFqzrg28EEjJzxxADZyjTXDsfwskRbibHSms9bbN2xK6GQcUxE2mrA2ULfYwsk5RQsVULUTj3pMMXpxRqP4zerzui2ZRZ3SqeNUwqnhmF861pEtcemZPY6ivcX41QK3ekCtpc1HndtY9xua1Lrhs4jd6qEbxHWzBPHok6qTpyxnn7ubZssBqSMz3uNrou1ayZGDn1ayAXtzCJPjAcxdNX1dpm5vyDB8GYtNKsQHuiX5xUd2EMAVfq4cFrZ6ncY1zrG5exH6mhJYbZfW7BgXxq7GsnzAAGkzgHCRADe5EEm1Hj1YdmVBTiaGsPGYkF4Mcrw3T2j3AcPJCzPLRNjKBKXyHAcf3VPUmreaHd1GoA5zqvtANSPmppY2AhCAj8u6n92fiyBgrvJTh4hyvtMFcwaa9vKnY9rBS4n5XGpdwKQe11Tk5sah8VZc2PyH2WPBU3DmhZSwUkKHRQQQQMXjrLjuMtygzxWBgrJAcWRPzxmzHZEj5x9GgFZb4dPDwqVXsgR25KrpuyQKcxfbxzQoRprnhu1ec8SfX5zeUo282Si9dBZ3JVdxzYHzP6xSiuBeHHFMvMwb1MKUq2dMi9vWdg2eCDo5wTvSaTVcdYGtZsT7HMswWtxx9GLw1RafYRcNqMhBhCbRdJszUKjQKwNNZbaryRs4kTYicuE24PWbqfxdJnrzrLbXnVBDMNHjX8ESXSKTMnAoE1AiLgjdj3zbBrY39Pxc72EikA7GvP2qxKZBkJ6G2RRWCw9d3nZKmTmQqP5PP9HgdtSTnZhNTJqBkwL3iqfoWxtbkLjLLSQc3dbFpmhe4kAh7VUUDcLzjb4nGzCbr5U1YoqAoLnSC9BPijnfMHxBP6i8cR762ryxPwe7HdGk62DVYoqxbwz8ygrDPjdPi3t11PpHp51GxuhMkoR3GFxAdMEv8j4tVpJ6qjefULEFTtRPzZ5kTE57RTxC4wg62qcYwupWx4dvvB2BR9ZGnNwCojpBYByeeYETrgm4HJjjS3SH64sbpyqz7336YMAcWyQFc9BeqjQHHUHS8CJ82N88apbPPE8N9X76DQ8PgwACtR4D5ofE9o14kpdVZFV2YMtmnKCybNLn3atspK6T1ZPYB3vQ1c4DbzZFgCpm6izEzxsY17in79ieo3cY965Cr5mkxca29VxcTaEtovdu9sKAL4VgCZzWkps5nnimX5JBEdVKYxTtMb6CcTkdWGFtXBTBuAMTpRNLXG5nG4bq9XXLkFS4oXpVS7KayqAMtrrqttpgwdAPNuzd6E4JskxdenwMq6qzMTDKoMqGDVEKkwCxCcbUtNpHGMLWMMk9MDrsPvcU8u2C89UmJmsfS5gQqswkz6TfXvthM3wPcuKaX7TUJJRzYstWsXRKUaPqqT3ppftCbXPFgia3mXkA5bk9Y3GWcTADGTnzKkTzbnL6hsgQW1FyvsFwUiWUJd5weeHkfaHt8iV3PKy99S6d831iLCfFWM6bYZgEBvyx5seHSpiaXRfSv4A2yDsf4Tb4EVsyDUJPUmZLnbFkJmw46A6PoQHdwfBbXWV47DFM6w5mKXCPmKzuAG1Vmw7D36n4oHd91r1VzTynVnhD1EA5UVh4qhiw2CnWgo2uAPxEpLYnvrCLiVprnzdPzvZZqMUxXRFWHwfshJDARRLvP933693aWxa5PeDNgMjZYgKJBV5e66Z1Mk5rYegEuSq7uyz8Mw3iuidtJeqBugbNCYeNdmeBPgKux8HcuFNqQaVwhP9vW8vyaU7DvuKEeXs1uyAgtk9RCua2Mx8rQqUwQigWNjXaJoSYqMT9SVEGUSYAGQiLnMFENqG1r87uhxV58hTwR8QED9cQkStFXeuZAMY6FWTZCsD5juC48KdqoUQYr77iBy7fW2quQNdPvwEUdhh1mzSTX2PPubCbm9rcdBxBQ2CBZizn1EsbPMic1X39t17scRE5F4Yank18EF4aUmJwwNHx5m1WKDQMZ1kJQRyhtRvAHTPqBdJCw5SHaEqBVpEQHUZwBKsQoTRj4Gk1opv6XfczoK3MLuprTMSx2maw5Gv6LhF2SWUvEXMMqoeqVzyP9g11dumkKQLMiAQa2VGaa7EF7Foj2ZDUhPM6PPiffHMhDMwWhRBywg3SC6aP9zz2TdMXweHv8rags9chFZ217aAP3bcCf5i1VZqPT9b8Ea7ykjjUy6PNwiSforRXN46suuRFREuhx6DuWDojythjH73wMAeKKx23rF4QfdUxzkC2mmmS4dq8Xx7Bda4e31EGab4t81Jk4dAVGjSrZC9wx89CAjovhoejgDTKNsN3ri4GjW9UD","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/manifest-key/package/witnesses.json b/fixtures/invalid/manifest-key/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/manifest-key/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/missing-required-file/expect.json b/fixtures/invalid/missing-required-file/expect.json new file mode 100644 index 0000000..8879409 --- /dev/null +++ b/fixtures/invalid/missing-required-file/expect.json @@ -0,0 +1 @@ +{"note":"A required file is missing.","rule":"package.file.required"} diff --git a/fixtures/invalid/missing-required-file/package/MANIFEST.json b/fixtures/invalid/missing-required-file/package/MANIFEST.json new file mode 100644 index 0000000..6ec09fd --- /dev/null +++ b/fixtures/invalid/missing-required-file/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/missing-required-file/package/document.json b/fixtures/invalid/missing-required-file/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/missing-required-file/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/missing-required-file/package/nodes.jsonl b/fixtures/invalid/missing-required-file/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/missing-required-file/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/missing-required-file/package/receipts.jsonl b/fixtures/invalid/missing-required-file/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/missing-required-file/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/missing-required-file/package/references.jsonl b/fixtures/invalid/missing-required-file/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/missing-required-file/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/missing-required-file/package/roster.json b/fixtures/invalid/missing-required-file/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/missing-required-file/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key:z4xcFfnTC6XJy4gzg9whfyMzcnxV7yM2XafMFynKXhAEvMgjfQCxSnjZaa53arz2iNo8v35ZN5SdAUcbFkbuvftcMczRT2CPhYsXkNYZhDzXWQVS5KZZkhnMDmwChWfgRHu4Bs6KHyEmvzwesTioW5yS3YtfR7mUPJAwWSRq9f23HRxzenGpVVBcVjpd8YDZ4Y1ZamcUfesnB6pGLrPtLDvGM7Te1cJWoRG4m3TetEF3i9V3W4CH43nouCwUPbjy7dpTNEWiCqaTPiPhV8UEWBD8b9e1729PwoUFyAFreuq6wvhphLKGHhFCFujrUtqDZPs6FFF1Q7Lpt9eFcjbxrZSAYsh9VTfxaUeQ4HmFqzrg28EEjJzxxADZyjTXDsfwskRbibHSms9bbN2xK6GQcUxE2mrA2ULfYwsk5RQsVULUTj3pMMXpxRqP4zerzui2ZRZ3SqeNUwqnhmF861pEtcemZPY6ivcX41QK3ekCtpc1HndtY9xua1Lrhs4jd6qEbxHWzBPHok6qTpyxnn7ubZssBqSMz3uNrou1ayZGDn1ayAXtzCJPjAcxdNX1dpm5vyDB8GYtNKsQHuiX5xUd2EMAVfq4cFrZ6ncY1zrG5exH6mhJYbZfW7BgXxq7GsnzAAGkzgHCRADe5EEm1Hj1YdmVBTiaGsPGYkF4Mcrw3T2j3AcPJCzPLRNjKBKXyHAcf3VPUmreaHd1GoA5zqvtANSPmppY2AhCAj8u6n92fiyBgrvJTh4hyvtMFcwaa9vKnY9rBS4n5XGpdwKQe11Tk5sah8VZc2PyH2WPBU3DmhZSwUkKHRQQQQMXjrLjuMtygzxWBgrJAcWRPzxmzHZEj5x9GgFZb4dPDwqVXsgR25KrpuyQKcxfbxzQoRprnhu1ec8SfX5zeUo282Si9dBZ3JVdxzYHzP6xSiuBeHHFMvMwb1MKUq2dMi9vWdg2eCDo5wTvSaTVcdYGtZsT7HMswWtxx9GLw1RafYRcNqMhBhCbRdJszUKjQKwNNZbaryRs4kTYicuE24PWbqfxdJnrzrLbXnVBDMNHjX8ESXSKTMnAoE1AiLgjdj3zbBrY39Pxc72EikA7GvP2qxKZBkJ6G2RRWCw9d3nZKmTmQqP5PP9HgdtSTnZhNTJqBkwL3iqfoWxtbkLjLLSQc3dbFpmhe4kAh7VUUDcLzjb4nGzCbr5U1YoqAoLnSC9BPijnfMHxBP6i8cR762ryxPwe7HdGk62DVYoqxbwz8ygrDPjdPi3t11PpHp51GxuhMkoR3GFxAdMEv8j4tVpJ6qjefULEFTtRPzZ5kTE57RTxC4wg62qcYwupWx4dvvB2BR9ZGnNwCojpBYByeeYETrgm4HJjjS3SH64sbpyqz7336YMAcWyQFc9BeqjQHHUHS8CJ82N88apbPPE8N9X76DQ8PgwACtR4D5ofE9o14kpdVZFV2YMtmnKCybNLn3atspK6T1ZPYB3vQ1c4DbzZFgCpm6izEzxsY17in79ieo3cY965Cr5mkxca29VxcTaEtovdu9sKAL4VgCZzWkps5nnimX5JBEdVKYxTtMb6CcTkdWGFtXBTBuAMTpRNLXG5nG4bq9XXLkFS4oXpVS7KayqAMtrrqttpgwdAPNuzd6E4JskxdenwMq6qzMTDKoMqGDVEKkwCxCcbUtNpHGMLWMMk9MDrsPvcU8u2C89UmJmsfS5gQqswkz6TfXvthM3wPcuKaX7TUJJRzYstWsXRKUaPqqT3ppftCbXPFgia3mXkA5bk9Y3GWcTADGTnzKkTzbnL6hsgQW1FyvsFwUiWUJd5weeHkfaHt8iV3PKy99S6d831iLCfFWM6bYZgEBvyx5seHSpiaXRfSv4A2yDsf4Tb4EVsyDUJPUmZLnbFkJmw46A6PoQHdwfBbXWV47DFM6w5mKXCPmKzuAG1Vmw7D36n4oHd91r1VzTynVnhD1EA5UVh4qhiw2CnWgo2uAPxEpLYnvrCLiVprnzdPzvZZqMUxXRFWHwfshJDARRLvP933693aWxa5PeDNgMjZYgKJBV5e66Z1Mk5rYegEuSq7uyz8Mw3iuidtJeqBugbNCYeNdmeBPgKux8HcuFNqQaVwhP9vW8vyaU7DvuKEeXs1uyAgtk9RCua2Mx8rQqUwQigWNjXaJoSYqMT9SVEGUSYAGQiLnMFENqG1r87uhxV58hTwR8QED9cQkStFXeuZAMY6FWTZCsD5juC48KdqoUQYr77iBy7fW2quQNdPvwEUdhh1mzSTX2PPubCbm9rcdBxBQ2CBZizn1EsbPMic1X39t17scRE5F4Yank18EF4aUmJwwNHx5m1WKDQMZ1kJQRyhtRvAHTPqBdJCw5SHaEqBVpEQHUZwBKsQoTRj4Gk1opv6XfczoK3MLuprTMSx2maw5Gv6LhF2SWUvEXMMqoeqVzyP9g11dumkKQLMiAQa2VGaa7EF7Foj2ZDUhPM6PPiffHMhDMwWhRBywg3SC6aP9zz2TdMXweHv8rags9chFZ217aAP3bcCf5i1VZqPT9b8Ea7ykjjUy6PNwiSforRXN46suuRFREuhx6DuWDojythjH73wMAeKKx23rF4QfdUxzkC2mmmS4dq8Xx7Bda4e31EGab4t81Jk4dAVGjSrZC9wx89CAjovhoejgDTKNsN3ri4GjW9UD","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/missing-required-file/package/witnesses.json b/fixtures/invalid/missing-required-file/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/missing-required-file/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/not-canonical/expect.json b/fixtures/invalid/not-canonical/expect.json new file mode 100644 index 0000000..53ad723 --- /dev/null +++ b/fixtures/invalid/not-canonical/expect.json @@ -0,0 +1 @@ +{"note":"A line that is valid JSON but not canonical JSON.","rule":"package.file.canonical"} diff --git a/fixtures/invalid/not-canonical/package/MANIFEST.json b/fixtures/invalid/not-canonical/package/MANIFEST.json new file mode 100644 index 0000000..ff84d14 --- /dev/null +++ b/fixtures/invalid/not-canonical/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"982fbecd0724047eaf9a9330e10b1c0ae77189ca9c262e04f4266eabef080412","size":11312},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/not-canonical/package/document.json b/fixtures/invalid/not-canonical/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/not-canonical/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/not-canonical/package/nodes.jsonl b/fixtures/invalid/not-canonical/package/nodes.jsonl new file mode 100644 index 0000000..cf82a49 --- /dev/null +++ b/fixtures/invalid/not-canonical/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key": "b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826", "id": "s0fn2fj", "kind": "document", "match_hash": "b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a", "node_hash": "a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe", "ord": 0, "own_hash": "34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f", "parent": null, "text_hash": "bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/not-canonical/package/provenance.json b/fixtures/invalid/not-canonical/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/not-canonical/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/not-canonical/package/receipts.jsonl b/fixtures/invalid/not-canonical/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/not-canonical/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/not-canonical/package/references.jsonl b/fixtures/invalid/not-canonical/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/not-canonical/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/not-canonical/package/roster.json b/fixtures/invalid/not-canonical/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/not-canonical/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/not-canonical/package/witnesses.json b/fixtures/invalid/not-canonical/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/not-canonical/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/receipt-root/expect.json b/fixtures/invalid/receipt-root/expect.json new file mode 100644 index 0000000..11f176b --- /dev/null +++ b/fixtures/invalid/receipt-root/expect.json @@ -0,0 +1 @@ +{"note":"A receipt whose Merkle root does not recompute.","rule":"doc.receipt.root"} diff --git a/fixtures/invalid/receipt-root/package/MANIFEST.json b/fixtures/invalid/receipt-root/package/MANIFEST.json new file mode 100644 index 0000000..ed10e69 --- /dev/null +++ b/fixtures/invalid/receipt-root/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"8528fc565e19f96b145c49875edbd433f57bcf896e2d7ccbc9c45cd27ca51b3a","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/receipt-root/package/document.json b/fixtures/invalid/receipt-root/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/receipt-root/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/receipt-root/package/nodes.jsonl b/fixtures/invalid/receipt-root/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/receipt-root/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/receipt-root/package/provenance.json b/fixtures/invalid/receipt-root/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/receipt-root/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/receipt-root/package/receipts.jsonl b/fixtures/invalid/receipt-root/package/receipts.jsonl new file mode 100644 index 0000000..7caeaea --- /dev/null +++ b/fixtures/invalid/receipt-root/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"2222222222222222222222222222222222222222222222222222222222222222","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/receipt-root/package/references.jsonl b/fixtures/invalid/receipt-root/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/receipt-root/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/receipt-root/package/roster.json b/fixtures/invalid/receipt-root/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/receipt-root/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/receipt-root/package/witnesses.json b/fixtures/invalid/receipt-root/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/receipt-root/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/receipt-signature/expect.json b/fixtures/invalid/receipt-signature/expect.json new file mode 100644 index 0000000..1ad486e --- /dev/null +++ b/fixtures/invalid/receipt-signature/expect.json @@ -0,0 +1 @@ +{"note":"A receipt changed after it was signed.","rule":"doc.receipt.signature"} diff --git a/fixtures/invalid/receipt-signature/package/MANIFEST.json b/fixtures/invalid/receipt-signature/package/MANIFEST.json new file mode 100644 index 0000000..b7263fb --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"bbf1f8303fa2a9562071f61ec399e003a3dd0df9038fe06c01e48ff93330228b","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/receipt-signature/package/document.json b/fixtures/invalid/receipt-signature/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/receipt-signature/package/nodes.jsonl b/fixtures/invalid/receipt-signature/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/receipt-signature/package/provenance.json b/fixtures/invalid/receipt-signature/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/receipt-signature/package/receipts.jsonl b/fixtures/invalid/receipt-signature/package/receipts.jsonl new file mode 100644 index 0000000..5f3f2ae --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:01Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/receipt-signature/package/references.jsonl b/fixtures/invalid/receipt-signature/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/receipt-signature/package/roster.json b/fixtures/invalid/receipt-signature/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/receipt-signature/package/witnesses.json b/fixtures/invalid/receipt-signature/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/receipt-signature/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/receipt-unsorted-nodes/expect.json b/fixtures/invalid/receipt-unsorted-nodes/expect.json new file mode 100644 index 0000000..488b6c5 --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/expect.json @@ -0,0 +1 @@ +{"note":"A receipt whose nodes are not sorted by ID.","rule":"doc.receipt.nodes"} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/MANIFEST.json b/fixtures/invalid/receipt-unsorted-nodes/package/MANIFEST.json new file mode 100644 index 0000000..2e9f7ec --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"0941ebc17ef445bcdc9a01d80f6ac35a017f4f2632d16b752ac77ca4cbd454c6","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/document.json b/fixtures/invalid/receipt-unsorted-nodes/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/nodes.jsonl b/fixtures/invalid/receipt-unsorted-nodes/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/provenance.json b/fixtures/invalid/receipt-unsorted-nodes/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/receipts.jsonl b/fixtures/invalid/receipt-unsorted-nodes/package/receipts.jsonl new file mode 100644 index 0000000..765651f --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/references.jsonl b/fixtures/invalid/receipt-unsorted-nodes/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/roster.json b/fixtures/invalid/receipt-unsorted-nodes/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/receipt-unsorted-nodes/package/witnesses.json b/fixtures/invalid/receipt-unsorted-nodes/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/receipt-unsorted-nodes/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/retired-live/expect.json b/fixtures/invalid/retired-live/expect.json new file mode 100644 index 0000000..be84d2d --- /dev/null +++ b/fixtures/invalid/retired-live/expect.json @@ -0,0 +1 @@ +{"note":"An ID that is both live and retired.","rule":"doc.id.retired-live"} diff --git a/fixtures/invalid/retired-live/package/MANIFEST.json b/fixtures/invalid/retired-live/package/MANIFEST.json new file mode 100644 index 0000000..aa2b9b9 --- /dev/null +++ b/fixtures/invalid/retired-live/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"ids.jsonl","sha256":"278fb71fde86a5cb3dfc34df75838695e9f1846d33b6ae8867967f02e6ebb1be","size":82},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/retired-live/package/document.json b/fixtures/invalid/retired-live/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/retired-live/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/retired-live/package/ids.jsonl b/fixtures/invalid/retired-live/package/ids.jsonl new file mode 100644 index 0000000..cfd1035 --- /dev/null +++ b/fixtures/invalid/retired-live/package/ids.jsonl @@ -0,0 +1 @@ +{"id":"jvnys4s","kind":"retired","node_kind":"sentence","rev":1,"successor":null} diff --git a/fixtures/invalid/retired-live/package/nodes.jsonl b/fixtures/invalid/retired-live/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/retired-live/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/retired-live/package/provenance.json b/fixtures/invalid/retired-live/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/retired-live/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/retired-live/package/receipts.jsonl b/fixtures/invalid/retired-live/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/retired-live/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/retired-live/package/references.jsonl b/fixtures/invalid/retired-live/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/retired-live/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/retired-live/package/roster.json b/fixtures/invalid/retired-live/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/retired-live/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/retired-live/package/witnesses.json b/fixtures/invalid/retired-live/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/retired-live/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/rev-without-corrections/expect.json b/fixtures/invalid/rev-without-corrections/expect.json new file mode 100644 index 0000000..3f1d840 --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/expect.json @@ -0,0 +1 @@ +{"note":"document.json's rev is not the number of corrections.","rule":"doc.correction.rev"} diff --git a/fixtures/invalid/rev-without-corrections/package/MANIFEST.json b/fixtures/invalid/rev-without-corrections/package/MANIFEST.json new file mode 100644 index 0000000..2643d89 --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"f52c8dc6afac0cd89fb325e7049e40ebb19d4f239500f2a0145aa3d6b9cdffa1","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/rev-without-corrections/package/document.json b/fixtures/invalid/rev-without-corrections/package/document.json new file mode 100644 index 0000000..7e502a0 --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":3,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/rev-without-corrections/package/nodes.jsonl b/fixtures/invalid/rev-without-corrections/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/rev-without-corrections/package/provenance.json b/fixtures/invalid/rev-without-corrections/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/rev-without-corrections/package/receipts.jsonl b/fixtures/invalid/rev-without-corrections/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/rev-without-corrections/package/references.jsonl b/fixtures/invalid/rev-without-corrections/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/rev-without-corrections/package/roster.json b/fixtures/invalid/rev-without-corrections/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/rev-without-corrections/package/witnesses.json b/fixtures/invalid/rev-without-corrections/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/rev-without-corrections/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/root-mismatch/expect.json b/fixtures/invalid/root-mismatch/expect.json new file mode 100644 index 0000000..7ff79c9 --- /dev/null +++ b/fixtures/invalid/root-mismatch/expect.json @@ -0,0 +1 @@ +{"note":"document.json's root is not the root node's node_hash.","rule":"doc.hash.root"} diff --git a/fixtures/invalid/root-mismatch/package/MANIFEST.json b/fixtures/invalid/root-mismatch/package/MANIFEST.json new file mode 100644 index 0000000..e0a3bfa --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"4dd2ee838c6f97c4702656c90044aa5afc7e4dfcdf565b5d2b4a9b1705bb65b3","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/root-mismatch/package/document.json b/fixtures/invalid/root-mismatch/package/document.json new file mode 100644 index 0000000..bd60397 --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"1111111111111111111111111111111111111111111111111111111111111111","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/root-mismatch/package/nodes.jsonl b/fixtures/invalid/root-mismatch/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/root-mismatch/package/provenance.json b/fixtures/invalid/root-mismatch/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/root-mismatch/package/receipts.jsonl b/fixtures/invalid/root-mismatch/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/root-mismatch/package/references.jsonl b/fixtures/invalid/root-mismatch/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/root-mismatch/package/roster.json b/fixtures/invalid/root-mismatch/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/root-mismatch/package/witnesses.json b/fixtures/invalid/root-mismatch/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/root-mismatch/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/signer-mismatch/expect.json b/fixtures/invalid/signer-mismatch/expect.json new file mode 100644 index 0000000..6b544ad --- /dev/null +++ b/fixtures/invalid/signer-mismatch/expect.json @@ -0,0 +1 @@ +{"note":"A receipt whose signature was made with another key than the signer it names.","rule":"doc.receipt.signature"} diff --git a/fixtures/invalid/signer-mismatch/package/MANIFEST.json b/fixtures/invalid/signer-mismatch/package/MANIFEST.json new file mode 100644 index 0000000..1c1c047 --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"c2f0b12ef0543bff761960e4855d5eca95d97d70a992a3b2cb5f28a43f6133f6","size":2183},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/signer-mismatch/package/document.json b/fixtures/invalid/signer-mismatch/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/signer-mismatch/package/nodes.jsonl b/fixtures/invalid/signer-mismatch/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/signer-mismatch/package/provenance.json b/fixtures/invalid/signer-mismatch/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/signer-mismatch/package/receipts.jsonl b/fixtures/invalid/signer-mismatch/package/receipts.jsonl new file mode 100644 index 0000000..d52601b --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"cara","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"r79yee8gempn3","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"vcC9VObpZjCTpSUXNI99WSZMToUFEuF01qivflW8zjrBj+X1K98NlJTgwzd/dlndVPFFpniV62Rb7shH9BuFDQ=="}} diff --git a/fixtures/invalid/signer-mismatch/package/references.jsonl b/fixtures/invalid/signer-mismatch/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/signer-mismatch/package/roster.json b/fixtures/invalid/signer-mismatch/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"lQ6M2DulKY4RkQLGTPGZD+CHlOOib4kBkwlccVNWRDPco1k5kHtelT/yUP4+CoAQnHnLu96vpeWztaee/9RmjR3bstGj+P5tOSrwFlPuyNUPOWPNjwCQLrVEyeUGBaA4+HRvFwK7C4OHB8EJWYtC0OuH+tRPlCdLpxlVcZZcM7dsZYe2BDNenbWfp4TeX2Oa+dThlceDY0m9MewwqUrd5xdo9tc8PS9R9o0ZUWf0vDw7Fc5AcsWwbf76lDLvIbyd0aCaHJ7eaK6DFsBuZFKVdlZlH0inJciAMF8dPoRuE+A0VlZTEOsOivNWprM5iLHzXse3zSoHLldWr0t4hWxHH3MBQ57Ucee8RTU6hFRfqfFRl6zJQyRZOFZZoYD9QwXkR3NmUzV/FcsOMHpbgTcY7O0TAajPnfpSTp+XdyPVBR7TlTsturUCpryP0ZX1S3VJk2IaneB123thtcOtWsbqdT3Bb846H7yudI95WVTixIS/KIwoCbekSf8Y9+iW/xRVSWLRVc1gpigDxXfieSA7bI+qiUBjiKR7QU1KFYZA58VcOQhzeMLY6an34rsW4WHAwzzSv8Q6vrwpn8Ct9fTsIeiZsWZLueNkIUfjR0G1bHHoT2RHKton0AMRjOUGSKUUB4DNZ5xzXvC0jvUMWlgHB9z2wBCsIkIDVWqSA2DD0xeIY2wSUVPwPc1MnBAf/Fx3poweUlcPWglR2VaO9ematC4hfLxxkGldGQt3C6ZLPsm96S7o6j88rwOqkDNIR1pNJOepgciJH/w4Xwtg9gJ52CpdlCeSllRQD74l95ysmZ2D/gLweNoUt61P0RYQQelio8VnPUNB1e2uK7zW9joG1k59CjJGQNvuZr6JkQ9+Hxo5xKEOy9KcpT6t48wTzbz3YMFDxTNl0/DzL8qdTU2UrSW6/TFgPLokbAQN00yhw0lg8cR/e1m+ujFyBeesL3luwE6HNcIyK5Y/+To04vR3OD7Uz8cnABxWyOeSBm2R2bu2fxeN0Hlv+qhoOYtbZ1DKx/aES4z51jATynEIdMIMSNhmVDoDiGODh9ocenzg/DUarjIzWltPFRyQj+tnFGTXp7C87s3yAf248ZB0HHhK1GCppxB4hsv89nNtWH1JdWjsc243s3f0WOZtJ1f+9yeybViJCW47ez7HkwtTq2AVeg+lHrb4TPCL5pBKwUOj5GVe2DzMFBtjilcl/ED4gev7DK383iyB4tGVZa1ALPKUyiyKV3sCRV/mN5DSGeASafI6OOjjUKifYCJaxOHFQGr6zvfhVj9L2Cl/hthxplTWoLpo4I7+oLPQJIrOMPf8FHLtRLAYthsxT3K02mVtUMhrviaVh5/kJKMMd4iRc8YXloC0r8roivoEPr5SzDprSffh8a2N2KRAHd3yrp4z7RxlpWKPWr5whD56q279S70A9r/r5r0bVzwabhKkTSJxc2LN72QondANsGFDYPD3Rm+FwSO2JwwgIG8GQxBbMWPOEqD0qDmaebNfP/EpbeF8mvA8v4e58CIv1LaHZuEky6vc16woEYHm11UuH6ChHbWxCoDXJsVM/jPme1vPlic38i9XYsE2c199gP1ikBGQANlryeIWH8wXtPUXNflNecMqIQkWAWSK/8jujgtylBQ/CklRyeW0+vyxV5eo8S8TfnonyG2eiHN1VS3HGLSidcYRi54IsOMtuR773QoLPZeRXlsNWO5kc3xcHU7K6olsMNtQhaFnkf3GATh9H80GUvEMK9u5yMUrCoYWuUy7JQhjsl+B1QbAFftdDu8ESgTOIKmFOLg+F9CH4lJrCqnwUdCs93zbJem2++Y64HRFLSUXwlhEUuQVugX7BejmcMYWMjYXROlatnznqYXcWW2uxx6ZNxQv0eB/CN1i4q1G8y9XUh4wz/caY8ly+eaTU5J4wGHfnUDpssu+TUvE5PGUs1gW6FswHlf1IXEnvKDIXKajbJgYnjEekVG8FxcSUc/10Mw/vqk/GQqdMOguf3mShlUIbtX2JVrA5ClZ9qza4HEXC7RkmxJLyc5dDyX/CuFdoDzrVu+1+JqRsFHGeLCo9rNvIQjvG09GQX6uDUavi25hCcOgug2DI0PuVLjcESFDyaYNdKo9GsiCEBpLPglp9viA2vX2kG6P2pidgsGfcBgdGuYGQbd23Qu9QpOd8AAuyWsm0dX6hKO2ChoAPVQxDNcj9N6UjumggVQ6zOuC0+gOcao/aPs/eH9agchdtnWKuL1clo4FduP4sdDtTvnJLFYnXONM//LSnjqSyBc7rzjJ2cxzPWQtLFawErzHXukl2eeP/xpDvLU0G6JroeJqBitHIoK00FGdxTUnrJBgy1DnBoIgUhxOvb1wtnx/O4DDS5tJZBDbl9XVbRmSfcljfQ5mB38hQ51CuYodHE9q12Bk1FtSwbVKvPHGb+9EdkbktJKRgdJubAQ+ajOCyMjEDCp9xLeKnlFL+WesI0Ro+rnmQL0qXVzkhZj8LP4a8yFYieIXCApLveflfv2yRJf3a/EML7yIgoEuzejddFrcbupWxDRqwS1YcLDkvGBEzjp8zuVnr72GfaFW/nvU9V9P/Z0fFS5hZhG5MnEp0Qzjsy/eKRI=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/signer-mismatch/package/witnesses.json b/fixtures/invalid/signer-mismatch/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/signer-mismatch/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/style-sup-sub/expect.json b/fixtures/invalid/style-sup-sub/expect.json new file mode 100644 index 0000000..0b76c24 --- /dev/null +++ b/fixtures/invalid/style-sup-sub/expect.json @@ -0,0 +1 @@ +{"note":"A run cannot be both a subscript and a superscript.","rule":"doc.run.style"} diff --git a/fixtures/invalid/style-sup-sub/package/MANIFEST.json b/fixtures/invalid/style-sup-sub/package/MANIFEST.json new file mode 100644 index 0000000..2ad5fde --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"0ddbad4bd01118676ced244f3d8296377b7d026bd07209b244bb750026511160","size":11317},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/style-sup-sub/package/document.json b/fixtures/invalid/style-sup-sub/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/style-sup-sub/package/nodes.jsonl b/fixtures/invalid/style-sup-sub/package/nodes.jsonl new file mode 100644 index 0000000..5eb3539 --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","style":["sub","sup"],"text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/style-sup-sub/package/provenance.json b/fixtures/invalid/style-sup-sub/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/style-sup-sub/package/receipts.jsonl b/fixtures/invalid/style-sup-sub/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/style-sup-sub/package/references.jsonl b/fixtures/invalid/style-sup-sub/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/style-sup-sub/package/roster.json b/fixtures/invalid/style-sup-sub/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/style-sup-sub/package/witnesses.json b/fixtures/invalid/style-sup-sub/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/style-sup-sub/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/text-edited/expect.json b/fixtures/invalid/text-edited/expect.json new file mode 100644 index 0000000..ef98d82 --- /dev/null +++ b/fixtures/invalid/text-edited/expect.json @@ -0,0 +1 @@ +{"note":"Text changed without its hashes.","rule":"doc.hash.text-hash"} diff --git a/fixtures/invalid/text-edited/package/MANIFEST.json b/fixtures/invalid/text-edited/package/MANIFEST.json new file mode 100644 index 0000000..a82f48f --- /dev/null +++ b/fixtures/invalid/text-edited/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"37b46719e48b84b0271e54cb85b1831852cebd8400b758f87bf1c261d1da3d36","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/text-edited/package/document.json b/fixtures/invalid/text-edited/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/text-edited/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/text-edited/package/nodes.jsonl b/fixtures/invalid/text-edited/package/nodes.jsonl new file mode 100644 index 0000000..12d3d79 --- /dev/null +++ b/fixtures/invalid/text-edited/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.5 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/text-edited/package/provenance.json b/fixtures/invalid/text-edited/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/text-edited/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/text-edited/package/receipts.jsonl b/fixtures/invalid/text-edited/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/text-edited/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/text-edited/package/references.jsonl b/fixtures/invalid/text-edited/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/text-edited/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/text-edited/package/roster.json b/fixtures/invalid/text-edited/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/text-edited/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"lQ6M2DulKY4RkQLGTPGZD+CHlOOib4kBkwlccVNWRDPco1k5kHtelT/yUP4+CoAQnHnLu96vpeWztaee/9RmjR3bstGj+P5tOSrwFlPuyNUPOWPNjwCQLrVEyeUGBaA4+HRvFwK7C4OHB8EJWYtC0OuH+tRPlCdLpxlVcZZcM7dsZYe2BDNenbWfp4TeX2Oa+dThlceDY0m9MewwqUrd5xdo9tc8PS9R9o0ZUWf0vDw7Fc5AcsWwbf76lDLvIbyd0aCaHJ7eaK6DFsBuZFKVdlZlH0inJciAMF8dPoRuE+A0VlZTEOsOivNWprM5iLHzXse3zSoHLldWr0t4hWxHH3MBQ57Ucee8RTU6hFRfqfFRl6zJQyRZOFZZoYD9QwXkR3NmUzV/FcsOMHpbgTcY7O0TAajPnfpSTp+XdyPVBR7TlTsturUCpryP0ZX1S3VJk2IaneB123thtcOtWsbqdT3Bb846H7yudI95WVTixIS/KIwoCbekSf8Y9+iW/xRVSWLRVc1gpigDxXfieSA7bI+qiUBjiKR7QU1KFYZA58VcOQhzeMLY6an34rsW4WHAwzzSv8Q6vrwpn8Ct9fTsIeiZsWZLueNkIUfjR0G1bHHoT2RHKton0AMRjOUGSKUUB4DNZ5xzXvC0jvUMWlgHB9z2wBCsIkIDVWqSA2DD0xeIY2wSUVPwPc1MnBAf/Fx3poweUlcPWglR2VaO9ematC4hfLxxkGldGQt3C6ZLPsm96S7o6j88rwOqkDNIR1pNJOepgciJH/w4Xwtg9gJ52CpdlCeSllRQD74l95ysmZ2D/gLweNoUt61P0RYQQelio8VnPUNB1e2uK7zW9joG1k59CjJGQNvuZr6JkQ9+Hxo5xKEOy9KcpT6t48wTzbz3YMFDxTNl0/DzL8qdTU2UrSW6/TFgPLokbAQN00yhw0lg8cR/e1m+ujFyBeesL3luwE6HNcIyK5Y/+To04vR3OD7Uz8cnABxWyOeSBm2R2bu2fxeN0Hlv+qhoOYtbZ1DKx/aES4z51jATynEIdMIMSNhmVDoDiGODh9ocenzg/DUarjIzWltPFRyQj+tnFGTXp7C87s3yAf248ZB0HHhK1GCppxB4hsv89nNtWH1JdWjsc243s3f0WOZtJ1f+9yeybViJCW47ez7HkwtTq2AVeg+lHrb4TPCL5pBKwUOj5GVe2DzMFBtjilcl/ED4gev7DK383iyB4tGVZa1ALPKUyiyKV3sCRV/mN5DSGeASafI6OOjjUKifYCJaxOHFQGr6zvfhVj9L2Cl/hthxplTWoLpo4I7+oLPQJIrOMPf8FHLtRLAYthsxT3K02mVtUMhrviaVh5/kJKMMd4iRc8YXloC0r8roivoEPr5SzDprSffh8a2N2KRAHd3yrp4z7RxlpWKPWr5whD56q279S70A9r/r5r0bVzwabhKkTSJxc2LN72QondANsGFDYPD3Rm+FwSO2JwwgIG8GQxBbMWPOEqD0qDmaebNfP/EpbeF8mvA8v4e58CIv1LaHZuEky6vc16woEYHm11UuH6ChHbWxCoDXJsVM/jPme1vPlic38i9XYsE2c199gP1ikBGQANlryeIWH8wXtPUXNflNecMqIQkWAWSK/8jujgtylBQ/CklRyeW0+vyxV5eo8S8TfnonyG2eiHN1VS3HGLSidcYRi54IsOMtuR773QoLPZeRXlsNWO5kc3xcHU7K6olsMNtQhaFnkf3GATh9H80GUvEMK9u5yMUrCoYWuUy7JQhjsl+B1QbAFftdDu8ESgTOIKmFOLg+F9CH4lJrCqnwUdCs93zbJem2++Y64HRFLSUXwlhEUuQVugX7BejmcMYWMjYXROlatnznqYXcWW2uxx6ZNxQv0eB/CN1i4q1G8y9XUh4wz/caY8ly+eaTU5J4wGHfnUDpssu+TUvE5PGUs1gW6FswHlf1IXEnvKDIXKajbJgYnjEekVG8FxcSUc/10Mw/vqk/GQqdMOguf3mShlUIbtX2JVrA5ClZ9qza4HEXC7RkmxJLyc5dDyX/CuFdoDzrVu+1+JqRsFHGeLCo9rNvIQjvG09GQX6uDUavi25hCcOgug2DI0PuVLjcESFDyaYNdKo9GsiCEBpLPglp9viA2vX2kG6P2pidgsGfcBgdGuYGQbd23Qu9QpOd8AAuyWsm0dX6hKO2ChoAPVQxDNcj9N6UjumggVQ6zOuC0+gOcao/aPs/eH9agchdtnWKuL1clo4FduP4sdDtTvnJLFYnXONM//LSnjqSyBc7rzjJ2cxzPWQtLFawErzHXukl2eeP/xpDvLU0G6JroeJqBitHIoK00FGdxTUnrJBgy1DnBoIgUhxOvb1wtnx/O4DDS5tJZBDbl9XVbRmSfcljfQ5mB38hQ51CuYodHE9q12Bk1FtSwbVKvPHGb+9EdkbktJKRgdJubAQ+ajOCyMjEDCp9xLeKnlFL+WesI0Ro+rnmQL0qXVzkhZj8LP4a8yFYieIXCApLveflfv2yRJf3a/EML7yIgoEuzejddFrcbupWxDRqwS1YcLDkvGBEzjp8zuVnr72GfaFW/nvU9V9P/Z0fFS5hZhG5MnEp0Qzjsy/eKRI=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/text-edited/package/witnesses.json b/fixtures/invalid/text-edited/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/text-edited/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/unknown-kind/expect.json b/fixtures/invalid/unknown-kind/expect.json new file mode 100644 index 0000000..fa2577b --- /dev/null +++ b/fixtures/invalid/unknown-kind/expect.json @@ -0,0 +1 @@ +{"note":"Kinds outside the list are refused.","rule":"package.schema"} diff --git a/fixtures/invalid/unknown-kind/package/MANIFEST.json b/fixtures/invalid/unknown-kind/package/MANIFEST.json new file mode 100644 index 0000000..6a97bb9 --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"75934bbf6f3baed92a8d6aa62c67f401b05d11c1c5dbfcf350da995a5ae6a5fa","size":11291},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/unknown-kind/package/document.json b/fixtures/invalid/unknown-kind/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/unknown-kind/package/nodes.jsonl b/fixtures/invalid/unknown-kind/package/nodes.jsonl new file mode 100644 index 0000000..ff81ae0 --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"aside","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/unknown-kind/package/provenance.json b/fixtures/invalid/unknown-kind/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/unknown-kind/package/receipts.jsonl b/fixtures/invalid/unknown-kind/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/unknown-kind/package/references.jsonl b/fixtures/invalid/unknown-kind/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/unknown-kind/package/roster.json b/fixtures/invalid/unknown-kind/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/unknown-kind/package/witnesses.json b/fixtures/invalid/unknown-kind/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/unknown-kind/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/unlisted-file/expect.json b/fixtures/invalid/unlisted-file/expect.json new file mode 100644 index 0000000..20ad8e6 --- /dev/null +++ b/fixtures/invalid/unlisted-file/expect.json @@ -0,0 +1 @@ +{"note":"A file the manifest does not list.","rule":"package.manifest.unlisted"} diff --git a/fixtures/invalid/unlisted-file/package/MANIFEST.json b/fixtures/invalid/unlisted-file/package/MANIFEST.json new file mode 100644 index 0000000..6be6656 --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/unlisted-file/package/document.json b/fixtures/invalid/unlisted-file/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/unlisted-file/package/nodes.jsonl b/fixtures/invalid/unlisted-file/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/unlisted-file/package/notes.txt b/fixtures/invalid/unlisted-file/package/notes.txt new file mode 100644 index 0000000..946d7b4 --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/notes.txt @@ -0,0 +1 @@ +stray diff --git a/fixtures/invalid/unlisted-file/package/provenance.json b/fixtures/invalid/unlisted-file/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/unlisted-file/package/receipts.jsonl b/fixtures/invalid/unlisted-file/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/unlisted-file/package/references.jsonl b/fixtures/invalid/unlisted-file/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/unlisted-file/package/roster.json b/fixtures/invalid/unlisted-file/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/unlisted-file/package/witnesses.json b/fixtures/invalid/unlisted-file/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/unlisted-file/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/unsafe-path/expect.json b/fixtures/invalid/unsafe-path/expect.json new file mode 100644 index 0000000..02a3e8b --- /dev/null +++ b/fixtures/invalid/unsafe-path/expect.json @@ -0,0 +1 @@ +{"note":"The manifest lists a path that leaves the package.","rule":"package.path.unsafe"} diff --git a/fixtures/invalid/unsafe-path/package/MANIFEST.json b/fixtures/invalid/unsafe-path/package/MANIFEST.json new file mode 100644 index 0000000..144138c --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"../escape.txt","sha256":"0000000000000000000000000000000000000000000000000000000000000000","size":1},{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/invalid/unsafe-path/package/document.json b/fixtures/invalid/unsafe-path/package/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/invalid/unsafe-path/package/nodes.jsonl b/fixtures/invalid/unsafe-path/package/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/invalid/unsafe-path/package/provenance.json b/fixtures/invalid/unsafe-path/package/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/invalid/unsafe-path/package/receipts.jsonl b/fixtures/invalid/unsafe-path/package/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/invalid/unsafe-path/package/references.jsonl b/fixtures/invalid/unsafe-path/package/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/invalid/unsafe-path/package/roster.json b/fixtures/invalid/unsafe-path/package/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/invalid/unsafe-path/package/witnesses.json b/fixtures/invalid/unsafe-path/package/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/invalid/unsafe-path/package/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/invalid/zip-symlink/expect.json b/fixtures/invalid/zip-symlink/expect.json new file mode 100644 index 0000000..3144aed --- /dev/null +++ b/fixtures/invalid/zip-symlink/expect.json @@ -0,0 +1 @@ +{"note":"An archive entry that is a symbolic link.","rule":"package.zip.entry"} diff --git a/fixtures/invalid/zip-symlink/package.sct.zip b/fixtures/invalid/zip-symlink/package.sct.zip new file mode 100644 index 0000000..694972b Binary files /dev/null and b/fixtures/invalid/zip-symlink/package.sct.zip differ diff --git a/fixtures/invalid/zip-traversal/expect.json b/fixtures/invalid/zip-traversal/expect.json new file mode 100644 index 0000000..17df561 --- /dev/null +++ b/fixtures/invalid/zip-traversal/expect.json @@ -0,0 +1 @@ +{"note":"An archive entry whose path leaves the package folder.","rule":"package.zip.entry"} diff --git a/fixtures/invalid/zip-traversal/package.sct.zip b/fixtures/invalid/zip-traversal/package.sct.zip new file mode 100644 index 0000000..2b53833 Binary files /dev/null and b/fixtures/invalid/zip-traversal/package.sct.zip differ diff --git a/fixtures/keys/ana.ed25519.hex b/fixtures/keys/ana.ed25519.hex new file mode 100644 index 0000000..f53ba8f --- /dev/null +++ b/fixtures/keys/ana.ed25519.hex @@ -0,0 +1 @@ +ed15ad1824fbb03ff808e8d7efde8494e43b89d7db6828019d0bd533827de0ea diff --git a/fixtures/keys/ben-spot.ed25519.hex b/fixtures/keys/ben-spot.ed25519.hex new file mode 100644 index 0000000..e7faaf1 --- /dev/null +++ b/fixtures/keys/ben-spot.ed25519.hex @@ -0,0 +1 @@ +235bbb5dba203a3304f4946308f1e1b0ea196256c30883ba9dcecbebf48c9308 diff --git a/fixtures/keys/ben.ed25519.hex b/fixtures/keys/ben.ed25519.hex new file mode 100644 index 0000000..5bfebc2 --- /dev/null +++ b/fixtures/keys/ben.ed25519.hex @@ -0,0 +1 @@ +da2b6906caf18b5bcc01e246c289a0314c33a52df11b568e0e09a25003f15c3a diff --git a/fixtures/keys/cara.ed25519.hex b/fixtures/keys/cara.ed25519.hex new file mode 100644 index 0000000..9b9496f --- /dev/null +++ b/fixtures/keys/cara.ed25519.hex @@ -0,0 +1 @@ +792b2ff45a7d18b96781fc65ef48529adcc786308710bdf34f0c4f7400a392c9 diff --git a/fixtures/keys/dana.ed25519.hex b/fixtures/keys/dana.ed25519.hex new file mode 100644 index 0000000..7264c58 --- /dev/null +++ b/fixtures/keys/dana.ed25519.hex @@ -0,0 +1 @@ +d561c68d0b5b83e0086a9a59170e6e93f47080dd1366bdbccddae57f8252337a diff --git a/fixtures/keys/smithlab-team-secret.hex b/fixtures/keys/smithlab-team-secret.hex new file mode 100644 index 0000000..21e4e5a --- /dev/null +++ b/fixtures/keys/smithlab-team-secret.hex @@ -0,0 +1 @@ +30fe6ec81905c8e0412719dd02bebe483c72ecd867332c76a35c67654ad5db18 diff --git a/fixtures/keys/wit.ed25519.hex b/fixtures/keys/wit.ed25519.hex new file mode 100644 index 0000000..6ca5589 --- /dev/null +++ b/fixtures/keys/wit.ed25519.hex @@ -0,0 +1 @@ +f3c3fe2604b52fd5c7115392be3c9dad905af954a210e7808f67bef92d31f82f diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/MANIFEST.json b/fixtures/packages/hale2026harmonic-damb.checks-only/MANIFEST.json new file mode 100644 index 0000000..90c52f9 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"assets/586f92512b294a1c325bfc16207771fb9acc7bb67bb206f25a429a055134056f.png","present":false,"sha256":"586f92512b294a1c325bfc16207771fb9acc7bb67bb206f25a429a055134056f","size":18213},{"path":"assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png","sha256":"a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75","size":73},{"path":"document.json","sha256":"37cc0709423fa2c19c5127813286f75e0f4a4aa86e2031d13cacf8a885daba65","size":1127},{"path":"ids.jsonl","sha256":"d19c4716a605352d4cd84f81381d99a5e2db6b59c88e926611dd13a5a16e4155","size":852},{"path":"locations.jsonl","sha256":"37a3f73ff3dc81082e98b4a02afff535fbdf0f1439cf56fdb39566d28076c6e2","size":7396},{"path":"nodes.jsonl","sha256":"30c5cd9adc5917419ee3bb6b79980b65bb3475c044d7d61a81bb512d0505bd04","size":41653},{"path":"pages.jsonl","sha256":"948177c6b7e5e361ac1da0ecff6b52406d3513f14d58cd27cd84f17e6f1c054e","size":438},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"references.jsonl","sha256":"137697ad84182a76c93b32a7dc0d91101e5bcf92586632f382d779bf2bd2035d","size":148},{"path":"witnesses.json","sha256":"99ae654df4fb461a424bb51edd476a89041182c7df9c98653a81b78031f92ada","size":1006}],"format":"scienting-package/1","key":"hale2026harmonic-damb"} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png b/fixtures/packages/hale2026harmonic-damb.checks-only/assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png new file mode 100644 index 0000000..9adf6a8 Binary files /dev/null and b/fixtures/packages/hale2026harmonic-damb.checks-only/assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png differ diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/document.json b/fixtures/packages/hale2026harmonic-damb.checks-only/document.json new file mode 100644 index 0000000..5817e56 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":45,"nodes":75},"fidelity":{"counts":{"F0":1,"F1":4,"F2":13,"F3":27},"lowest":"F0"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","key_id":"dc3a5e64b55a972b","scheme":"hmac-team"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"hale2026harmonic-damb","kind":"article","language":"en","license":{"text":"All rights reserved by the publisher (fictional)."},"meta":{"DOI":"10.5555/example.hale.2026","author":[{"family":"Hale","given":"R."},{"family":"Osei","given":"M."}],"container-title":"Journal of Example Chemistry","issued":{"date-parts":[[2026,3,2]]},"page":"101-109","title":"Harmonic bond parameters for small organic molecules from a two-step fit","type":"article-journal","volume":"14"},"meta_hash":"e141d5c008f4732f6b0b02d2d81f00e4f7ea8659585f52378a7678e2a47ccf4e","policy":"checks-only","relations":[],"rev":12,"root":"aeee58f4d92f6fca5ebcc70c101a5febae21bd4e3e5dd0e4ca674cb84800dabd","store":"smithlab","version":{"date":"2026-03-02","type":"version-of-record"},"work":{"key":"hale2026harmonic-damb","same_as":["doi:10.5555/example.hale.2026"]}} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/ids.jsonl b/fixtures/packages/hale2026harmonic-damb.checks-only/ids.jsonl new file mode 100644 index 0000000..9fee9f9 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/ids.jsonl @@ -0,0 +1,11 @@ +{"id":"b-p01-text-003","kind":"alias","successor":"hca6dc5"} +{"id":"b-p02-table-001","kind":"alias","successor":"hj4s7pb"} +{"id":"ayea71r","kind":"retired","node_kind":"sentence","rev":4,"successor":"xjns57z"} +{"id":"ncx2v4f","kind":"retired","node_kind":"paragraph","rev":5,"successor":"gwzbj3s"} +{"id":"r3w6j1w","kind":"retired","node_kind":"paragraph","rev":6,"successor":null} +{"id":"v8e4z6z","kind":"retired","node_kind":"sentence","rev":6,"successor":null} +{"id":"ex460rm","kind":"retired","node_kind":"cell","rev":8,"successor":null} +{"id":"k03dm2e","kind":"retired","node_kind":"cell","rev":8,"successor":null} +{"id":"qacy341","kind":"retired","node_kind":"cell","rev":8,"successor":null} +{"id":"rncchma","kind":"retired","node_kind":"row","rev":8,"successor":null} +{"id":"w97feam","kind":"retired","node_kind":"cell","rev":8,"successor":null} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/locations.jsonl b/fixtures/packages/hale2026harmonic-damb.checks-only/locations.jsonl new file mode 100644 index 0000000..b0a0961 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/locations.jsonl @@ -0,0 +1,46 @@ +{"boxes":[[72,72,493.2,83.8]],"node":"mhkp90t","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,85.95,183.15,97.75]],"node":"s1b3bjf","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,99.9,540,111.7],[72,113.85,270.9,125.65]],"node":"mhp0at8","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,127.8,405.45,139.6]],"node":"v3063qv","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,141.75,142.2,153.55]],"node":"wrxng89","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,155.7,540,167.5],[72,169.65,218.25,181.45]],"node":"kea5026","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,183.6,540,195.4],[72,197.55,540,209.35],[72,211.5,183.15,223.3]],"node":"rr20tev","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,225.45,540,237.25],[72,239.4,83.7,251.2]],"node":"hca6dc5","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,253.35,364.5,265.15]],"node":"ec5jc93","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,267.3,417.15,279.1]],"node":"a4jrz2t","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,72,112.95,83.8]],"node":"y65m5cd","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,85.95,540,97.75],[72,99.9,229.95,111.7]],"node":"xjns57z","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,113.85,376.2,125.65]],"node":"qwgfg51","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,127.8,306,139.6]],"node":"vya7t4n","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,141.75,300,291.75]],"node":"rzxn46v","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,301.75,300,451.75]],"node":"cx816pa","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,461.75,329.4,473.55]],"node":"z86b2za","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,475.7,148.05,487.5]],"node":"caehhp6","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,489.65,235.8,501.45]],"node":"nms5qjg","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,503.6,259.2,515.4]],"node":"wxxhb3s","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,517.55,95.4,529.35]],"node":"hshknn3","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,531.5,101.25,543.3]],"node":"mb6xd86","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,545.45,101.25,557.25]],"node":"xyy7x6c","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,559.4,200.7,571.2]],"node":"ycwgbx1","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,573.35,183.15,585.15]],"node":"d1mhw8b","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,587.3,200.7,599.1]],"node":"k6a6616","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,601.25,183.15,613.05]],"node":"x3ns64d","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,615.2,159.75,627]],"node":"a49pag5","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,629.15,101.25,640.95]],"node":"vd76637","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,643.1,101.25,654.9]],"node":"c20cna6","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,657.05,101.25,668.85]],"node":"ztww0g8","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,671,101.25,682.8]],"node":"j6y45v6","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,684.95,107.1,696.75]],"node":"bnyvykm","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,281.25,101.25,293.05]],"node":"avbhhey","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,295.2,101.25,307]],"node":"w0gr97q","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,309.15,101.25,320.95]],"node":"b5gd0h1","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,323.1,101.25,334.9]],"node":"w264b74","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,337.05,107.1,348.85]],"node":"exms5gc","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,351,101.25,362.8]],"node":"yvkd7xr","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,364.95,101.25,376.75]],"node":"jv1741a","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,378.9,107.1,390.7]],"node":"m1p1n2g","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,392.85,101.25,404.65]],"node":"ganq1ns","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,406.8,107.1,418.6]],"node":"ryhrskg","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,698.9,323.55,710.7]],"node":"f44s64g","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,712.85,446.4,724.65]],"node":"tb6syqq","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,726.8,370.35,738.6]],"node":"vxsdvzq","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/nodes.jsonl b/fixtures/packages/hale2026harmonic-damb.checks-only/nodes.jsonl new file mode 100644 index 0000000..704d58c --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/nodes.jsonl @@ -0,0 +1,75 @@ +{"align_key":"73e1dcf3ecf4c2646dcda07bc6cd0737e53d558673446d5008a050ab55e34f51","id":"xxqgpzr","kind":"document","match_hash":"b10e788d778e93d11fcd5b7afe480c744ddadc5756059a2907b10e42fe150f3a","node_hash":"aeee58f4d92f6fca5ebcc70c101a5febae21bd4e3e5dd0e4ca674cb84800dabd","ord":0,"own_hash":"1e1c0a042df01d115ebd6ad7a11767de2203f8ce28d99dca0962a0386679ccc9","parent":null,"text_hash":"0a51cd3b3a2eec1768706c11c74a00f5ddacb26cbfdfeb0c2ae74ed5fb3a1aee"} +{"align_key":"740b904666b6b804ecc509a156d97599256c6e122fce798296b10f23135fd2d8","id":"n5qsc9k","kind":"front","match_hash":"9723d605ea537dd125808f4554a0fc7e9d88acb24dde0d69f728f76d462a7512","node_hash":"7bf80c1e21781846947dc2820af3dfe28d5bfcea3c6becfb15c277cecc9b67e1","ord":0,"own_hash":"76184bd872d41b4a1e7144cd938ff98e726f624161a0e048298d2462f4fbcebd","parent":"xxqgpzr","text_hash":"9723d605ea537dd125808f4554a0fc7e9d88acb24dde0d69f728f76d462a7512"} +{"align_key":"85822515b8d30d8e7d6856677292c6d52ac01408a1f4a77fcfd768ab353569fd","id":"cgah0gr","kind":"title","match_hash":"ea1bbfcaf7fe35e0e55b33eb4d034a5c7f2450c79b4d4808bc1e68c6883aa0d9","node_hash":"b83340764d0b14a97f560351d7707fcafe5ef88e29a990d45f5dad9d7ac56890","ord":0,"own_hash":"6662b63efd4c8fa2292f869d74f4621c43deb986b77cede381bf54bc753427d6","parent":"n5qsc9k","text_hash":"ea1bbfcaf7fe35e0e55b33eb4d034a5c7f2450c79b4d4808bc1e68c6883aa0d9"} +{"align_key":"85822515b8d30d8e7d6856677292c6d52ac01408a1f4a77fcfd768ab353569fd","fidelity":"F2","id":"mhkp90t","kind":"sentence","match_hash":"ea1bbfcaf7fe35e0e55b33eb4d034a5c7f2450c79b4d4808bc1e68c6883aa0d9","node_hash":"063511b457939fc79103b0c92bcd869e9e60d0d79e5f4ff53e1eb8bae321bee8","ord":0,"own_hash":"0e97e19eae4aacf7b6b61a1140afea1c728b2b21799f9157a47e18fbf73097d6","parent":"cgah0gr","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"ea1bbfcaf7fe35e0e55b33eb4d034a5c7f2450c79b4d4808bc1e68c6883aa0d9","withheld":true} +{"align_key":"ce8e2360807a66a2747c20b68e31078383c6f4c30cbed1fa9936f94c6838da10","fidelity":"F2","id":"s1b3bjf","kind":"authors","match_hash":"8082ef3352a42a4e7c1c4635982c16bb9b2411775855dcdb0660bcee9bc16dc3","node_hash":"2c72165f1eae4d7469dc45e7eccd3090bd3e436e3fe18e2465ad85ae284cb0b0","ord":1,"own_hash":"f70286aad77f371f1d916a2edeb90ed5c61aa9eec3606da07823df62fdf71649","parent":"n5qsc9k","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"8082ef3352a42a4e7c1c4635982c16bb9b2411775855dcdb0660bcee9bc16dc3","withheld":true} +{"align_key":"a51d90fcfedd34dc094dd4ca6f2fba7b0924ce03edb3d87ea4ba238c69022140","id":"xm3zcy9","kind":"abstract","match_hash":"415a8e815243b76fd0ef1accc4631ddd089b7cb893a9e79f63c75e8378f2d10c","node_hash":"e117bb73af3aeb9bcc824fa13b0b9206aae26d2ded1ca8083d834c38101f2954","ord":2,"own_hash":"ae5c9c076b138544e4f8921da1f5838c1a5d04783911c5b98f084032e2237a1a","parent":"n5qsc9k","text_hash":"415a8e815243b76fd0ef1accc4631ddd089b7cb893a9e79f63c75e8378f2d10c"} +{"align_key":"a51d90fcfedd34dc094dd4ca6f2fba7b0924ce03edb3d87ea4ba238c69022140","id":"vcmfvx9","kind":"paragraph","match_hash":"415a8e815243b76fd0ef1accc4631ddd089b7cb893a9e79f63c75e8378f2d10c","node_hash":"1ce3545316f51522d8e4ce579d88f6d727e0c3ef1e89bd0c088ad13ba581a1b8","ord":0,"own_hash":"103a1fafd6650afad54130d0fb721a3587d6904efcf738f606313c32f6ea8406","parent":"xm3zcy9","text_hash":"415a8e815243b76fd0ef1accc4631ddd089b7cb893a9e79f63c75e8378f2d10c"} +{"align_key":"2446b40b59e305558df1e96a2999ae7661ee2a093a2271919b80bcfecd27ef4a","fidelity":"F2","id":"mhp0at8","kind":"sentence","match_hash":"3f2f4d29ebacc0fd2539d6e8d74ce91988a28eed786f236296cfcb1d3e3160d8","node_hash":"fa1ab60ed7cf75096a4b578111cf134f25bb6f79d3a6bdbfd50a681c11aef001","ord":0,"own_hash":"0f7bcb166b066ff55461fbafb8c80c7ee99a007814a47dbb5f1a997dd6af146a","parent":"vcmfvx9","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"3f2f4d29ebacc0fd2539d6e8d74ce91988a28eed786f236296cfcb1d3e3160d8","withheld":true} +{"align_key":"4c4b2441a5f5ce14fd1a22bac71a5ca164572fec67e6f5306a5fb041f8651de8","fidelity":"F2","id":"v3063qv","kind":"sentence","match_hash":"2c842774bf2f0cf35874c21a39b3c8e37aed60f69c78ab7548bb8118e4f0ff35","node_hash":"ad20d9fc4440d88f815b3ed8ffc9a02da727edde2f916a560859303b682cb7e4","ord":1,"own_hash":"2210c4a6b9bde5b514a89ff45ea75031a05940de245857816fbf8cc25a8a0f85","parent":"vcmfvx9","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"2c842774bf2f0cf35874c21a39b3c8e37aed60f69c78ab7548bb8118e4f0ff35","withheld":true} +{"align_key":"fb4cfa363b0cbacbae23a9eee5f90d564f13d66deb1669cef22399f26ad4c908","attrs":{"level":1},"id":"p36k8t6","kind":"section","label":"1","match_hash":"ee5737e1a7383abbc83279a6c2904a1865355ea37e3b8e0dc286c66bf2c9289f","node_hash":"8e88c006344534dcdbad270f7d2733d19278e6a017acf17d802b27b718759ec3","ord":1,"own_hash":"d6987fcfcc59e3c840e38f69cd8b0f19f12a05098b5c2826a77087a230743ade","parent":"xxqgpzr","text_hash":"c4cd1d13b4f0d02c3298406187ee0141094a96ff16331c21163a557507158492"} +{"align_key":"ccdb89934b47e8b8bbbc65b3860a3158608252d5f108c0885b40d7726994aa81","id":"j8rdzk6","kind":"heading","match_hash":"0e20a78430a5d2996a268cd27076e70ef4e92d5496363dbf0bb8d9a0bdd1fe98","node_hash":"a885b81ff8e37fabab03cd3c2735f291e9ad80459ac7667f4477c0b6064c433b","ord":0,"own_hash":"0cce5ff8d380dedec933eb3aaaedf29d79dabca723dbe279240f83bbc75d7b3a","parent":"p36k8t6","text_hash":"0e20a78430a5d2996a268cd27076e70ef4e92d5496363dbf0bb8d9a0bdd1fe98"} +{"align_key":"ccdb89934b47e8b8bbbc65b3860a3158608252d5f108c0885b40d7726994aa81","fidelity":"F2","id":"wrxng89","kind":"sentence","match_hash":"0e20a78430a5d2996a268cd27076e70ef4e92d5496363dbf0bb8d9a0bdd1fe98","node_hash":"63434ad314933ba962e9d55e61b6938a4f340e8ed6655d00a00d38ca90778fba","ord":0,"own_hash":"4b4748ebfc7e82f326995058ee270a53a95ef32fde0b16b6575ff174f50c5377","parent":"j8rdzk6","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"0e20a78430a5d2996a268cd27076e70ef4e92d5496363dbf0bb8d9a0bdd1fe98","withheld":true} +{"align_key":"20c362585be6e33d555703bd098e38e3009fd07430f8784949cd30d16c1c280f","id":"tgp1qey","kind":"paragraph","match_hash":"5d385c8da69c51f88db862f9f8990f4b400da92c0f717eacc1554daafbf88240","node_hash":"667ebf5629cce6df2c5440d309199be71927c02f374beee7e2d5753d083a5d67","ord":1,"own_hash":"103a1fafd6650afad54130d0fb721a3587d6904efcf738f606313c32f6ea8406","parent":"p36k8t6","text_hash":"d70638159e2bc6647273fc19abc2dde7907b1764339c91a9a3acdeec48cc9d2b"} +{"align_key":"534ed962405d1953e0fff6d3f2be3f8a107802d4b675d49b097db4d86a6895fd","fidelity":"F2","id":"kea5026","kind":"sentence","match_hash":"44433a74cb8a8ac14bc432c73d8214467d592451c867e8366c8078e31d147c20","node_hash":"94475ae4b33e4e1145dd1a3bcd8b57df808bd23541ed39c2cbc100d94cf09df7","ord":0,"own_hash":"47e81f4d38ccf735eee88146d49d54dc968c6d8ff7ef0d1d209ee3193ed220fd","parent":"tgp1qey","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"d26d51b8125eb7eaeb4ca33e6b23a428ea7191121b3da2d5484d0669b1ae7e2e","withheld":true} +{"align_key":"ca0d330d37d08e676a14c3aa1b30316392edc2baef7140e3f5340b9c47c17bd1","fidelity":"F2","id":"rr20tev","kind":"sentence","match_hash":"db463b068510be091c368023e6c8c914c676194ab1ce4610058c5512ad509697","node_hash":"deeac72321b47dcbc96ac0ccd417266b434aafd6ac243f8c6fc9fec85009b9d3","ord":1,"own_hash":"fa8d493788899a9726f7e405b2343010d1f08472a30adf46ecc0adee40ebdaba","parent":"tgp1qey","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"81e3eba9fa3eb5d919aba915ac8d5971b2463d1e9157d929b33782e305f7af41","withheld":true} +{"align_key":"3b70b2ee313f4b81169167f9b94274cd9a5caa328b6e4d6b3604f96c08a0f38f","fidelity":"F1","id":"tkxsmts","kind":"equation","label":"(1)","match_hash":"3b70b2ee313f4b81169167f9b94274cd9a5caa328b6e4d6b3604f96c08a0f38f","node_hash":"2edb62dcc7bfd51c37db068ee66efe945e5bc60719ec8990c563a66039ef390e","ord":0,"own_hash":"9c5ee44736a367e95e71131ab7d7a0ce45416dc2386a092f4387372e1bb5b950","parent":"rr20tev","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"f5f6ab94585adb5a9adb51cbaf12347418703cb6e976c792da4cf1706a904b86","withheld":true} +{"align_key":"108a3f1c7ba588a3817db5fc9339bb337c13adb485070abe949c80ebf8decaf9","fidelity":"F2","id":"hca6dc5","kind":"sentence","match_hash":"8083cb37b9021c86bd6b109054b2a403aad1834df62e419dc87b65a4a524f86c","node_hash":"7e48a32644e1cf75401d2a077eb9b44359904cc930876938db664b9d572ae2ba","ord":2,"own_hash":"1d428e5d2907404347d96796ac72677e23397787a8c7d75904e63444104ab9b4","parent":"tgp1qey","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"f2c5d2ef44c075bfc34e63066294f0ae8717097bc40ae36fc6ab71a42740ddd6","withheld":true} +{"align_key":"29f2758dbcb716be40546c66991156ed71ad75e18d58c7eb2ead0a974c024d98","id":"v7q07ne","kind":"paragraph","match_hash":"5dbddace07737f8eaf137d377f9cae81fad7960826fb0c4cda22e05da131c3ae","node_hash":"87438ba64ab54d282992b473ec5114a00c75fcf10579c2cedc8d5bb39f5cd3f4","ord":2,"own_hash":"103a1fafd6650afad54130d0fb721a3587d6904efcf738f606313c32f6ea8406","parent":"p36k8t6","text_hash":"e4e3d35002830eaca719b1daffe6f69e1178ae4d0d0d63cb48583381b30fd994"} +{"align_key":"18bbc434b98cf635f227acf5a3ec4d2e18814313689cb400de2e84815d1fb05b","fidelity":"F1","id":"ec5jc93","kind":"sentence","match_hash":"b72b77abb5003dcf58a07d14c469224ca5a4c2d869aa0f9636f405d34276bee8","node_hash":"2294e0dce748acf61dadf4cc39fccb20e7c2498ee13983ccad992cc569f93792","ord":0,"own_hash":"61db158a8480075191b42d17cf79729aa1707dff0a959ec2982d3fcdbf51736f","parent":"v7q07ne","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"fb34c55630da4a53640ea45cb8ae6ff7203f717089c6d124a594793a4bbdf052","withheld":true} +{"align_key":"8a358d2aa5d3c292972d57bafca52ec38d39ec7a94e9f1e8d313bb40f84c6d18","fidelity":"F0","id":"a4jrz2t","kind":"sentence","match_hash":"f9433133fa445421b20872ade78f026037c5f196517c919d9a7898ab6fb34f70","node_hash":"31ee31135ec964ceea3b99be108dc38d38046498c191854f94dbf85c322fb3be","ord":1,"own_hash":"9e7f035814c27e45c8276b6a08b8d4ed940ebe7a02eb08c7b9e122419fa80d8a","parent":"v7q07ne","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"de3da699a85726c8d4d5422b41e2f2463205bdec38cf16c7a9bdd1678861df49","withheld":true} +{"align_key":"f900c547e8971f0ac6d1f62dae772455eccc51566f1d6d6b3b26d6b3ddea5986","attrs":{"level":1},"id":"d400rz3","kind":"section","label":"2","match_hash":"f4eff397b084f1e571c0e008d3818fb0c121b9d5fa82e8c9128fd8a11175da57","node_hash":"268413c1509c24e700b419e8481cf0db8cb92e8ffd38f9a97631ced88a263bff","ord":2,"own_hash":"f628f52a30833081ec4c96ce11e7a5962fdd92b197447d870868e8023921a7e7","parent":"xxqgpzr","text_hash":"d87ad0a243fd855b8cad50aba311f5af9bbcf583ed9c71b2f822e2abf9be5993"} +{"align_key":"9acd205a8daba021ac1f790cf1f00333b3eb28b8079c37749a0d89601858d22b","id":"m27nkzr","kind":"heading","match_hash":"49856b3c5eecfd363da5adfc43334836922679ceee9a03184f32da2970216c8f","node_hash":"6ec3ca5769457a8725e46ea86285357a3f56f39eaa5c2b1aefa7c1cb0abc73db","ord":0,"own_hash":"0cce5ff8d380dedec933eb3aaaedf29d79dabca723dbe279240f83bbc75d7b3a","parent":"d400rz3","text_hash":"49856b3c5eecfd363da5adfc43334836922679ceee9a03184f32da2970216c8f"} +{"align_key":"9acd205a8daba021ac1f790cf1f00333b3eb28b8079c37749a0d89601858d22b","fidelity":"F2","id":"y65m5cd","kind":"sentence","match_hash":"49856b3c5eecfd363da5adfc43334836922679ceee9a03184f32da2970216c8f","node_hash":"e31a9c1ac2955ddf7239d75d2f631547c74d144f99aa8ebc99e5ca7c7ed9085e","ord":0,"own_hash":"d4382327152c5c23f3c93dfe55758d65d07130ff123c2de78723956d94b53539","parent":"m27nkzr","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"49856b3c5eecfd363da5adfc43334836922679ceee9a03184f32da2970216c8f","withheld":true} +{"align_key":"88965d90b8b00097c7aaaa42cb5fe2436be95ec0762a9434050fb980750acb49","id":"gwzbj3s","kind":"paragraph","match_hash":"4c06718e151db68f23388da5aebaca05166e362886e386647866b93707570042","node_hash":"80f7b977440e1ec3c2713c5b3ec04fefd14df9177d9c858e10db866a40b88c25","ord":1,"own_hash":"103a1fafd6650afad54130d0fb721a3587d6904efcf738f606313c32f6ea8406","parent":"d400rz3","text_hash":"295bdc8f7e2f6a68819f9ef405c31bf9a4a4fd66f5e82d9fdaaf1d8258000dc5"} +{"align_key":"6b41e63d7dc3261437a2a67ca5f644ce5c17f7e9f16fde2babb76ea297e0cc26","fidelity":"F0","id":"xjns57z","kind":"sentence","match_hash":"967dee63417f16d4fb8e9fc9188b78afcec932e18f869985edcf5bd4e6a3ae8c","node_hash":"632f2deb0eaf30efa19ec17c0047b4f62527fe7aae6576de2450a341840aff90","ord":0,"own_hash":"9bb78576a640cd5ba64ab31d3d04a6444944392ec30ed14d2a4aaf9a380b6bad","parent":"gwzbj3s","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"967dee63417f16d4fb8e9fc9188b78afcec932e18f869985edcf5bd4e6a3ae8c","withheld":true} +{"align_key":"0fa5dd094b4445e742120e267a80c83284bee7a8530e4ad0ca1c303ba503dfb6","fidelity":"F2","id":"qwgfg51","kind":"sentence","match_hash":"e9a6aa86ac9d3a5cfbabf1d1a7336162092c09be275de3423cad1f3f7d807160","node_hash":"603026e9c4efc6dbee7cf383907cc263217df357731d21ee942bbb780304b98d","ord":1,"own_hash":"26fdbaf06b910e291be931f654830c1a1c1aed03efe9cce7271c7c0d5f4aa058","parent":"gwzbj3s","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"a2d885008f91838ed75044a7eb9baca8ac9a2b42c700f7c9034f781cbeab553f","withheld":true} +{"align_key":"f853fa1c2805901aaa4b5bee777ca968d9973fb864075a0702728ccaa52b2c91","id":"ppvbzn0","kind":"footnote","label":"a","match_hash":"3803689753b6e310fefeae28060af0b7cbac0084795f2288786dd046ac2edc1d","node_hash":"98d19cb4044f3e7998c5d554f10039e93271671fa7c70e1544256d59512aaa57","ord":2,"own_hash":"42106f1ead27d8af253acb8a50899e48bc15f0a543ef68dccc071de641eee54b","parent":"d400rz3","text_hash":"3803689753b6e310fefeae28060af0b7cbac0084795f2288786dd046ac2edc1d"} +{"align_key":"f853fa1c2805901aaa4b5bee777ca968d9973fb864075a0702728ccaa52b2c91","fidelity":"F2","id":"vya7t4n","kind":"sentence","match_hash":"3803689753b6e310fefeae28060af0b7cbac0084795f2288786dd046ac2edc1d","node_hash":"73767e47fe372357ee61915a799313a03890356e510c3d42f3e6edff3b2de47c","ord":0,"own_hash":"54998e6f01f44d6d23a6a8d6cc50ff73cbd1cf488e642971d4e89cfe10f29f25","parent":"ppvbzn0","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"3803689753b6e310fefeae28060af0b7cbac0084795f2288786dd046ac2edc1d","withheld":true} +{"align_key":"e922516f638d9f0755514963ebeba48976a888b6e1f0ab5d8204b8f973c1a020","id":"v7cx6qs","kind":"figure","label":"Figure 1","match_hash":"3f3274a1dbdabb2be5b9e3aaf882267f40ee5998f586b12ba6d9d86e29a48989","node_hash":"27b1442761a566fdc9cd11eecf5610bce8712d7e8ee039d18e9d96f12fb3744b","ord":3,"own_hash":"37d060f9e33e44399b2083366c5653e5d4cee0bc87965f6fdbeef219b459404a","parent":"d400rz3","text_hash":"3f3274a1dbdabb2be5b9e3aaf882267f40ee5998f586b12ba6d9d86e29a48989"} +{"align_key":"342411e519a65ad5e3f1dff4b87e9bec2f3117b514a3cb969ab970db7ab2304c","attrs":{"crop":{"dpi":300,"media_type":"image/png","sha256":"586f92512b294a1c325bfc16207771fb9acc7bb67bb206f25a429a055134056f"},"image":{"media_type":"image/png","native":true,"sha256":"a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75"}},"id":"rzxn46v","kind":"panel","label":"a","match_hash":"342411e519a65ad5e3f1dff4b87e9bec2f3117b514a3cb969ab970db7ab2304c","node_hash":"bc2cd137483278fad8ec6d39dbd63713acc0bcc7dafef7007d74986a3f3df4ce","ord":0,"own_hash":"9ea47ecefb7570b6d53009000759433924cf6aef57060ad592ba55c6e6a9fd29","parent":"v7cx6qs","text_hash":"342411e519a65ad5e3f1dff4b87e9bec2f3117b514a3cb969ab970db7ab2304c"} +{"align_key":"342411e519a65ad5e3f1dff4b87e9bec2f3117b514a3cb969ab970db7ab2304c","id":"cx816pa","kind":"panel","label":"b","match_hash":"342411e519a65ad5e3f1dff4b87e9bec2f3117b514a3cb969ab970db7ab2304c","node_hash":"408840125a11826b3926a1bd74873badcacc36ff5d04965bf7552e86643767ba","ord":1,"own_hash":"4042a6c64ebff7453faf9d1b836529382f4e708c552ceb8ba8804184375ad57a","parent":"v7cx6qs","text_hash":"342411e519a65ad5e3f1dff4b87e9bec2f3117b514a3cb969ab970db7ab2304c"} +{"align_key":"e922516f638d9f0755514963ebeba48976a888b6e1f0ab5d8204b8f973c1a020","id":"eb18hq4","kind":"caption","match_hash":"3f3274a1dbdabb2be5b9e3aaf882267f40ee5998f586b12ba6d9d86e29a48989","node_hash":"86e87c68050a9ae0669d618196d215935d9f20349ecf3d48e8e754fd0367a864","ord":2,"own_hash":"2aa668b20e140fe0e196cf24db7a541a84794050efa6ba0f59c7036b9048d26c","parent":"v7cx6qs","text_hash":"3f3274a1dbdabb2be5b9e3aaf882267f40ee5998f586b12ba6d9d86e29a48989"} +{"align_key":"db7fd2fe721a77655d9f3d0bd688e7421eec8ebf34894bc77c50c77440058375","fidelity":"F2","id":"z86b2za","kind":"sentence","match_hash":"2395607722d0d2f7b667002a16e259ca91b11b121c525a468fefa4c7885f414e","node_hash":"615a6342f9a89fbafeba6965a8d7377b69a1a5bb1ba7b63b4afacf79eb648409","ord":0,"own_hash":"c19a1b9f03c1f8418ae02f1c38038b7efabdd1bcad7af0b2ae82403871c2f9b2","parent":"eb18hq4","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"2395607722d0d2f7b667002a16e259ca91b11b121c525a468fefa4c7885f414e","withheld":true} +{"align_key":"c6b029913d981eba480dbe333618ecef777e6fc8cfccafe55543438306d22b7d","fidelity":"F2","id":"caehhp6","kind":"sentence","match_hash":"39757eaa1ded3669c58bd8422a2e62a169732d594d6127b9a2d918fca83b788b","node_hash":"7f5463906446805d9125371ff32346ecce5bad029a13cc3da486a1daaf90c568","ord":1,"own_hash":"8c56a488c88cb66e6185df550c96d089519fe4051d72e943bd6b8652673c81e1","parent":"eb18hq4","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"39757eaa1ded3669c58bd8422a2e62a169732d594d6127b9a2d918fca83b788b","withheld":true} +{"align_key":"427202114fb14f7d74101f408c06fce2dcc4945668d18cc16ae6d9f53ae8a78f","fidelity":"F2","id":"nms5qjg","kind":"sentence","match_hash":"7e35eccee50fabecd210f1b3066b2de569ac2d01f90df03a91f7ae1dcfc239a3","node_hash":"7269e72e010dd5e99473aced819415fde7e5dc773fc56e83b7838695370b60d4","ord":2,"own_hash":"688c65e32ceb4d47401408c9170e31ade5d95500add8c852a0f366b15fe8661c","parent":"eb18hq4","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"7e35eccee50fabecd210f1b3066b2de569ac2d01f90df03a91f7ae1dcfc239a3","withheld":true} +{"align_key":"c71fe08f63da9864148d4eefc1560988ca34a139dc1c7d13b852462bade1fe10","attrs":{"columns":[{"header_path":["hshknn3"],"id":"kw15683"},{"header_path":["mb6xd86","ycwgbx1"],"id":"wdtrcqt"},{"header_path":["mb6xd86","d1mhw8b"],"id":"pge4yxn"},{"header_path":["xyy7x6c","k6a6616"],"id":"dh9a2te"},{"header_path":["xyy7x6c","x3ns64d"],"id":"xdk3d93"}]},"id":"hj4s7pb","kind":"table","label":"Table 1","match_hash":"a1f271f528fad641e05a8fb47b8a1177589f07762a89f56da4b7fd5ac3a70afe","node_hash":"75e87520edf52737712afe516c39ba2a82b39cccb5bc53cb0316c906fd0b0b28","ord":4,"own_hash":"b9f7ef8811b0b7b58306d249901f55a80e0cfa04c90f6bf9b204bec104a6d30e","parent":"d400rz3","text_hash":"63991cfc76be1a3c8e2c94a9e553afca00fd9c5363b574a63f37bfe848457b33"} +{"align_key":"9425ebf2474288aa3ba3fcc0cc809c89daa9f43a07925752d32a470c8fb18e61","id":"dnyp9c1","kind":"caption","match_hash":"7c94e294ed39e5a6b59aa07680278c1fe63a3ee202b8f1fba1e33864e3291b27","node_hash":"6cffafe17480657a4866349593c0bdb1cb226e8df86b8070ec008b3c40ca6cfa","ord":0,"own_hash":"2aa668b20e140fe0e196cf24db7a541a84794050efa6ba0f59c7036b9048d26c","parent":"hj4s7pb","text_hash":"7c94e294ed39e5a6b59aa07680278c1fe63a3ee202b8f1fba1e33864e3291b27"} +{"align_key":"9425ebf2474288aa3ba3fcc0cc809c89daa9f43a07925752d32a470c8fb18e61","fidelity":"F2","id":"wxxhb3s","kind":"sentence","match_hash":"7c94e294ed39e5a6b59aa07680278c1fe63a3ee202b8f1fba1e33864e3291b27","node_hash":"5165816c9b697c21600c7bcf0dcebc28112f55b89ad726876a2a0b8b5a04bc26","ord":0,"own_hash":"e9428353bb1af8b78212a4d4d9875e796dee13ef7459890b4d3785673e7131e1","parent":"dnyp9c1","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"7c94e294ed39e5a6b59aa07680278c1fe63a3ee202b8f1fba1e33864e3291b27","withheld":true} +{"align_key":"407230a97eee045d8c55dc144e768cf16ffad1225c90dbeebea0698e7cc45530","id":"nwwd4pb","kind":"table-head","match_hash":"cab6284a87e0b1042f060896b205429c6d6ea1f10e048cae0999e77a2a2b919a","node_hash":"f6d67053102891d70e0d44afe96f9ade9ba0447462884f1a193f67d78a6e6886","ord":1,"own_hash":"c6def727a6807f1d6414d60635eeedefaeee93aac7c14f8a5d5d1b79566ac000","parent":"hj4s7pb","text_hash":"cc3477b6261ecc70b0e58395612c9d2783f0a5c7ccf541004630239696af5d9b"} +{"align_key":"14331d699bee2bb04ddc82202600f2ebea53dbf0f92991eb43311ef0fcc5b678","id":"nytt74z","kind":"row","match_hash":"823699ccad7f80a19843c855a20a04b64463733202306d7c65ca8896b99062ba","node_hash":"2a92587460cb6c040902442871c58b74a3d9a040b99439f9ad27dce7a6ded2ae","ord":0,"own_hash":"c14e86865b4d8b396d94c6b195daf29936dc6a7f6c243eda677b64ea3f9e070a","parent":"nwwd4pb","text_hash":"823699ccad7f80a19843c855a20a04b64463733202306d7c65ca8896b99062ba"} +{"align_key":"8abb77e8d7225aac2dfa04d8b4d07b1c5dac9bae11887108b6e662197ca6fab7","attrs":{"colspan":1,"column":"kw15683","role":"column-header","rowspan":2},"fidelity":"F1","id":"hshknn3","kind":"cell","match_hash":"42c4f8f5ff77f36a537e727e485fee068c229e6b739cd042b465cd91ee37ba12","node_hash":"22fe587abe87f454a726af78f5d04403fd67f167dde3c3c8afebb23f1a7af0c1","ord":0,"own_hash":"117a0d397781effddf13120f808302b92ece2618354ae7c292043beed0137fc6","parent":"nytt74z","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"42c4f8f5ff77f36a537e727e485fee068c229e6b739cd042b465cd91ee37ba12","withheld":true} +{"align_key":"b65b164330b4a893b44d15a62db3f1445f5b7ebec58d82976343d050e91bb9d2","attrs":{"colspan":2,"column":"wdtrcqt","role":"column-header","rowspan":1},"fidelity":"F1","id":"mb6xd86","kind":"cell","match_hash":"09f4a80580115fe6532dea0b16a682b55c38e4c5ad1d4fd8602797b904e956d6","node_hash":"5e14bcace3e6db5b5453043e9bad935ca534625c46b1904be5ab5cb3b6e0e369","ord":1,"own_hash":"0111848778578a911fa7136f0b146b0e6e0a1513cac854fc755efbcbf4fc4001","parent":"nytt74z","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"09f4a80580115fe6532dea0b16a682b55c38e4c5ad1d4fd8602797b904e956d6","withheld":true} +{"align_key":"b9b486fb8f7fbbf9f67e963c8560c610fa4ea57fe65d85b4ccfbc1cbd3aa7dd9","attrs":{"colspan":2,"column":"dh9a2te","role":"column-header","rowspan":1},"fidelity":"F1","id":"xyy7x6c","kind":"cell","match_hash":"3509a66b57462a5c2829ba8ce34ffad83417cf626f228c7da1271418be00e10a","node_hash":"50721da8c605fff13d63b78106df3e1a290988365fb3189e6e1fb0eb3a551cea","ord":2,"own_hash":"9f4cf7d39f173355a44e762a9a01ade3bfcdda576de149606ae9addde99caf51","parent":"nytt74z","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"3509a66b57462a5c2829ba8ce34ffad83417cf626f228c7da1271418be00e10a","withheld":true} +{"align_key":"6386e9549a1b5b9fd530b855569e2bb2dc6e2448f80b0517e7d9269a15bb830d","id":"kba3nve","kind":"row","match_hash":"c6dce3fbfb3282f72800ff7cc949b0efe1d0071dee5de39b585fe0b2152d4572","node_hash":"92fdfb4796af1f8b2b597c4be327279ccfeef2dc424435c04774d8f6f05fa38e","ord":1,"own_hash":"c14e86865b4d8b396d94c6b195daf29936dc6a7f6c243eda677b64ea3f9e070a","parent":"nwwd4pb","text_hash":"abe75539244158ab0f8981ed6a698775b2f5465c53fc7958356f0388e71e8cd0"} +{"align_key":"10f170f47cf82f8db4cd4cf059aafee7f88d0f8a3962b423bd853bfc9cd411af","attrs":{"colspan":1,"column":"wdtrcqt","role":"column-header","rowspan":1},"fidelity":"F1","id":"ycwgbx1","kind":"cell","match_hash":"300d5edc7b0b54189f26bf496f79bef269290c14a884f067f1e92e94a6a15816","node_hash":"0f95e71bfe5db7deed136eb8d8ff3642526162667eeed2d96200c5342cc4ae00","ord":0,"own_hash":"6aa91735ac704815358af5da0c85780249d766ad3a9464b8a53cb36aca1a87c2","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"0412d2f6ed80f8b34dff64f2060cfd8425475e29463ac93364922608bfd3e485","withheld":true} +{"align_key":"93c8465fedad3bae9fbd481d2f84c6f0f15d43dd9ef34ee5d02fcff154cc3f5f","attrs":{"colspan":1,"column":"pge4yxn","role":"column-header","rowspan":1},"fidelity":"F1","id":"d1mhw8b","kind":"cell","match_hash":"0ebcbae54182a7ace5434c531ca4e8ae6eb0e43bfac9826e72fc8597ac5d86c8","node_hash":"5b71fbecd31de53b488e4fb0292329fea241b6c73d12d75e8fab5c6c0c4a92f5","ord":1,"own_hash":"2ceccee18b45b5b69622a18aae79b6cd911239f28f9ffd2f1901ec867947eade","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"4d99d81040101a0d6c3adb1a1be8679e5a92805556fef417490b67222d7ae6d2","withheld":true} +{"align_key":"10f170f47cf82f8db4cd4cf059aafee7f88d0f8a3962b423bd853bfc9cd411af","attrs":{"colspan":1,"column":"dh9a2te","role":"column-header","rowspan":1},"fidelity":"F1","id":"k6a6616","kind":"cell","match_hash":"300d5edc7b0b54189f26bf496f79bef269290c14a884f067f1e92e94a6a15816","node_hash":"a55c56c063fdfd5241f2f1c045aedc443a45603f98f0baebd4534990fb10ac27","ord":2,"own_hash":"5769c252754a0f09e88cea5cc77b94f266d0b725b10806d723e105ba2057d91a","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"0412d2f6ed80f8b34dff64f2060cfd8425475e29463ac93364922608bfd3e485","withheld":true} +{"align_key":"93c8465fedad3bae9fbd481d2f84c6f0f15d43dd9ef34ee5d02fcff154cc3f5f","attrs":{"colspan":1,"column":"xdk3d93","role":"column-header","rowspan":1},"fidelity":"F1","id":"x3ns64d","kind":"cell","match_hash":"0ebcbae54182a7ace5434c531ca4e8ae6eb0e43bfac9826e72fc8597ac5d86c8","node_hash":"22e7eb1c11e6486721dec31a69971a24ca54b12a32f5facc83696acc62f7084e","ord":3,"own_hash":"75e6379b0da25976eff36b003b51769f6d7399822ccdaa67556789d7b9d89042","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"4d99d81040101a0d6c3adb1a1be8679e5a92805556fef417490b67222d7ae6d2","withheld":true} +{"align_key":"87cb6b8f8be2d6bff665a5981e9c86cd24764fe836f85f5b34e9dfbd1f96581b","id":"dwwm2fa","kind":"table-body","match_hash":"cca0a627a4f90bd941adf546af165fdadec89e2ea369b43afa6ee47aa3ed8d15","node_hash":"64cda9bed383831a0020c0d391f8b01d64d0acfcc3a54d71957b208ccc526d73","ord":2,"own_hash":"bf77bb0a83f9ab4f0e4b567071e4c6bddc0b955a63c1c60198a354c5165395c4","parent":"hj4s7pb","text_hash":"cca0a627a4f90bd941adf546af165fdadec89e2ea369b43afa6ee47aa3ed8d15"} +{"align_key":"1830ea7c02f1384dd6e5aa1ade14435955d21e06908d6bf106773c8d213a866d","id":"re8z87t","kind":"row","match_hash":"0d491bd777b4bc314525a57a6d8fe2a6d8984013b065dade76365bc869fab740","node_hash":"86d63cb19c3732b781c48f0eff64575578f8a2117d16ac4499d867dd67a5a2ab","ord":0,"own_hash":"c14e86865b4d8b396d94c6b195daf29936dc6a7f6c243eda677b64ea3f9e070a","parent":"dwwm2fa","text_hash":"0d491bd777b4bc314525a57a6d8fe2a6d8984013b065dade76365bc869fab740"} +{"align_key":"1830ea7c02f1384dd6e5aa1ade14435955d21e06908d6bf106773c8d213a866d","attrs":{"colspan":5,"column":"kw15683","role":"row-group-header","rowspan":1},"fidelity":"F1","id":"a49pag5","kind":"cell","match_hash":"0d491bd777b4bc314525a57a6d8fe2a6d8984013b065dade76365bc869fab740","node_hash":"9ac8f2fb662b956442232dd64ea6d88add7557928538c7437eb9ec119f8bad6a","ord":0,"own_hash":"6e9333ed21248be5b04074fc23a69ecd5db963ec49f1110a6d56c8a717203377","parent":"re8z87t","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"0d491bd777b4bc314525a57a6d8fe2a6d8984013b065dade76365bc869fab740","withheld":true} +{"align_key":"67610b86cb00e1ce4b20310fed50032876a624a2288b7f0b6c481d1f3d7a5ba1","attrs":{"header_path":["a49pag5","vd76637"]},"id":"g8d2pjb","kind":"row","match_hash":"f6551181a0c1d137f7f99d8a2a514610e1c48e98914690e059b288fc5d467aa6","node_hash":"a9b0dfe1e8c3f7294584c1db1aaefd0f28c85b85394b64b540be64ac9833f8bf","ord":1,"own_hash":"c14e86865b4d8b396d94c6b195daf29936dc6a7f6c243eda677b64ea3f9e070a","parent":"dwwm2fa","text_hash":"f6551181a0c1d137f7f99d8a2a514610e1c48e98914690e059b288fc5d467aa6"} +{"align_key":"7c35b37e66e8e0b71831776db71655f2deca87096cda2341a527b53fa07b8768","attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"fidelity":"F1","id":"vd76637","kind":"cell","match_hash":"dfef88eae90d650b6002b3e5f2a9e931a8cce1910c225884a601f7ec3c9eca84","node_hash":"562512c92adbb7f389f92eb75107821899eda0cdea08a213bda473f0b11d7cae","ord":0,"own_hash":"234941d2c16a0f378f59ce1e4faf7e4671d2b55989beafb34aea586ae64e2c66","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"dfef88eae90d650b6002b3e5f2a9e931a8cce1910c225884a601f7ec3c9eca84","withheld":true} +{"align_key":"9df4869eb9769862199036065318395ff4a2b2bc6fb1ff9592bea75fce1fe05f","attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"fidelity":"F1","id":"c20cna6","kind":"cell","match_hash":"9df4869eb9769862199036065318395ff4a2b2bc6fb1ff9592bea75fce1fe05f","node_hash":"abb7664dc98d0ee667aebd9b7610e55f5c9bc869f7dc46b99c7fb9c3d455a578","ord":1,"own_hash":"694a9c6f62a5a65deeffc2b8eefd6b423f6538771542d986b430ac21fb5ff4fb","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"9df4869eb9769862199036065318395ff4a2b2bc6fb1ff9592bea75fce1fe05f","withheld":true} +{"align_key":"277fc47aa73ebeddb378e0fcc71fa771dad884f5859d18848f383e25bf0c692b","attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"fidelity":"F1","id":"ztww0g8","kind":"cell","match_hash":"277fc47aa73ebeddb378e0fcc71fa771dad884f5859d18848f383e25bf0c692b","node_hash":"96ad7d08afb66d50980f93df190b7e2c8dc6ead051a326107b091024d7fc0b8e","ord":2,"own_hash":"00136f42f2e6b1a7021b9f12690712db6cabbeb40f19e3d9a702276b9d2d4d9b","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"277fc47aa73ebeddb378e0fcc71fa771dad884f5859d18848f383e25bf0c692b","withheld":true} +{"align_key":"082ddf5b66d3e2cc3f699c7a5de6a6c447ebc5bf1ac851a5c7ac021957b92a26","attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"fidelity":"F1","id":"j6y45v6","kind":"cell","match_hash":"082ddf5b66d3e2cc3f699c7a5de6a6c447ebc5bf1ac851a5c7ac021957b92a26","node_hash":"d6c4ed45dee22a29f44a420bd982a0c414bb056392a106754b769e8c423f0894","ord":3,"own_hash":"b85e1e7c98df9c3889c57bed8653084df32670242402f084ad8868c43769b0ce","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"082ddf5b66d3e2cc3f699c7a5de6a6c447ebc5bf1ac851a5c7ac021957b92a26","withheld":true} +{"align_key":"cbcb31f00106d632d678f653d2befc6ada85a099891a8abe28b3a88d04fa8dcb","attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"fidelity":"F1","id":"bnyvykm","kind":"cell","match_hash":"cbcb31f00106d632d678f653d2befc6ada85a099891a8abe28b3a88d04fa8dcb","node_hash":"67fb7bbcd4a066f7ce473dd1f7a9b2df80034a11c45c0b78e9cd5e2f2b3c4339","ord":4,"own_hash":"ecb111483310ec0da34913f320da7b462298d69b46386ba32fbcf4450ad9e770","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"cbcb31f00106d632d678f653d2befc6ada85a099891a8abe28b3a88d04fa8dcb","withheld":true} +{"align_key":"2ae24e81d93421f14986b4784ba49d86fb12510de0b27e96eea9b590074329ce","attrs":{"header_path":["a49pag5","avbhhey"]},"id":"kx2kz2y","kind":"row","match_hash":"91236b2e4d26eed27e3c517a153887c32f321c8da636c47a24841690fd070ec4","node_hash":"f15f59e650b736028bd4dc9b13a702a7901a1aafa3bc6160bdcd296fc4880baf","ord":2,"own_hash":"c14e86865b4d8b396d94c6b195daf29936dc6a7f6c243eda677b64ea3f9e070a","parent":"dwwm2fa","text_hash":"91236b2e4d26eed27e3c517a153887c32f321c8da636c47a24841690fd070ec4"} +{"align_key":"974f2a3d89c8ed1c268639ae351f4347e9c9fa6b5c1aed0ade0589dd869fc801","attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"fidelity":"F1","id":"avbhhey","kind":"cell","match_hash":"55a2e817c13ed9765b396def6fd9ca1096323fb3b5bc0c444e37bbdb915a079f","node_hash":"eb10b5277b42f7353ea0a9a0e7d91b05fbf97869c535fcf26704e8d797b3a110","ord":0,"own_hash":"3d455386e0c36ac492fca1fa2e285fa998cc2c5aaea23537e01f5856f48e24cf","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"55a2e817c13ed9765b396def6fd9ca1096323fb3b5bc0c444e37bbdb915a079f","withheld":true} +{"align_key":"99baed178e147af160906d3277e2573a7c20d0deb0faf6ac09a996e0f9c43379","attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"fidelity":"F1","id":"w0gr97q","kind":"cell","match_hash":"99baed178e147af160906d3277e2573a7c20d0deb0faf6ac09a996e0f9c43379","node_hash":"6666b9df2abec28391223a3df4d07ca19d5a1654fe3866ed7a6e97cdca1b0674","ord":1,"own_hash":"03dd2adcba820674c8e4fba4d9237c80d6915efe49f24f5c7e2be8531aaaaa4f","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"99baed178e147af160906d3277e2573a7c20d0deb0faf6ac09a996e0f9c43379","withheld":true} +{"align_key":"7d1b43e12c7f140959922e1eec95e8c5827632a6e67d73c4cfcdbf505ca95c0c","attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"fidelity":"F1","id":"b5gd0h1","kind":"cell","match_hash":"7d1b43e12c7f140959922e1eec95e8c5827632a6e67d73c4cfcdbf505ca95c0c","node_hash":"62e24e5298e7fe0be536874f070fd0ef981f791ccfddadaf9b06530379586ceb","ord":2,"own_hash":"cf803f1948bdc4da350dfb24250ead049197f735f4eb445221bbd4e6fc740537","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"7d1b43e12c7f140959922e1eec95e8c5827632a6e67d73c4cfcdbf505ca95c0c","withheld":true} +{"align_key":"826676b6dfae525b01e453d01b5f93e4923db49a2628a433e0a484a378fd411e","attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"fidelity":"F1","id":"w264b74","kind":"cell","match_hash":"826676b6dfae525b01e453d01b5f93e4923db49a2628a433e0a484a378fd411e","node_hash":"0a9c09857c9b11324ec83f9892b0429cc4df45d60a0aa0412dbb9eb7cecd3c79","ord":3,"own_hash":"e6b59ef73276faf1bc05eea725fa7d216f29bfb95da1b52f34b5b90a9b0e3575","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"826676b6dfae525b01e453d01b5f93e4923db49a2628a433e0a484a378fd411e","withheld":true} +{"align_key":"86a322f595c37c519980a38471c7cd9f56945d6216a918440650edad83e1a241","attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"fidelity":"F1","id":"exms5gc","kind":"cell","match_hash":"86a322f595c37c519980a38471c7cd9f56945d6216a918440650edad83e1a241","node_hash":"fed115c18c383f2907e75cc471cf340d6f3d20f648d63b753718314b872de34c","ord":4,"own_hash":"805dbe4c589a50e19b19a696b71d8e2508cf1af87a3436f8a64ff4a025bc57a6","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"86a322f595c37c519980a38471c7cd9f56945d6216a918440650edad83e1a241","withheld":true} +{"align_key":"c38dd8bec28759d5335b21144e911a28d2f55b6385b2cd42054a2ba2f75eda8e","attrs":{"header_path":["a49pag5","yvkd7xr"]},"id":"ke0jxpn","kind":"row","match_hash":"de98690f51e23b74adc25f0b45dc3cce01dbf1e9f1764f3ba14910890e33d9df","node_hash":"666ae7b11f9e8c97e1758930c3f8fac176a8a25c65fa5803dc3e5b50acbf5bff","ord":3,"own_hash":"c14e86865b4d8b396d94c6b195daf29936dc6a7f6c243eda677b64ea3f9e070a","parent":"dwwm2fa","text_hash":"de98690f51e23b74adc25f0b45dc3cce01dbf1e9f1764f3ba14910890e33d9df"} +{"align_key":"34f35723ac187b148f88cf7632eea4b2cd4285ff94aad8dda1d442c5e5ee237f","attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"fidelity":"F1","id":"yvkd7xr","kind":"cell","match_hash":"b92adb81e3b67ad07c476de82e9378cf41a8fba1442fa8b893962b117ac2e058","node_hash":"4f4dbc7bbdaac038984e4c6f07367c933bfed0f3a970cea41d4bd1845ce9195e","ord":0,"own_hash":"c5ba85a0917ed365aaeee52ea449ba181d77567a7d2a3b5e8f3fd8eef8a2c857","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"b92adb81e3b67ad07c476de82e9378cf41a8fba1442fa8b893962b117ac2e058","withheld":true} +{"align_key":"137fe6261d4ef4eae4bb97ecdfa829a6887bd67747f2838b8b120dc80efa7dc8","attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"fidelity":"F1","id":"jv1741a","kind":"cell","match_hash":"137fe6261d4ef4eae4bb97ecdfa829a6887bd67747f2838b8b120dc80efa7dc8","node_hash":"8f732390e8ac8ba522cdb67c46189db861c26aafdfedacf129f947d6b2a128ea","ord":1,"own_hash":"c158d07b27fda55bd3ea0907b775d8a66a0b04c4563e5be966711ec349203c96","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"137fe6261d4ef4eae4bb97ecdfa829a6887bd67747f2838b8b120dc80efa7dc8","withheld":true} +{"align_key":"43fd2f1c22b3dfc7e3b540a202f52df9c26dd75459b8f9dfe5dd7d74c03fe03a","attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"fidelity":"F1","id":"m1p1n2g","kind":"cell","match_hash":"43fd2f1c22b3dfc7e3b540a202f52df9c26dd75459b8f9dfe5dd7d74c03fe03a","node_hash":"732641f8361854b254a62facda90dd0e714e5a0439be7347bf796fc5f711157c","ord":2,"own_hash":"5cd6129407e69a99ba1bed33ad67ba50bc5c6d618974c05cd4b1fc0b07b538b5","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"43fd2f1c22b3dfc7e3b540a202f52df9c26dd75459b8f9dfe5dd7d74c03fe03a","withheld":true} +{"align_key":"51596c6b3a0ef682aa95d6a624e81ea347c77ec9b02a502c35e71c5c2d7b20bb","attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"fidelity":"F1","id":"ganq1ns","kind":"cell","match_hash":"51596c6b3a0ef682aa95d6a624e81ea347c77ec9b02a502c35e71c5c2d7b20bb","node_hash":"61de3c81c480e5d184a9a1be34ff38d25fca9fd9d8cb785662bef70cccd81078","ord":3,"own_hash":"90daf1e25a4da521d43e0ae5ceafe452b59149de8224c4514f1dd27b55f2a59e","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"51596c6b3a0ef682aa95d6a624e81ea347c77ec9b02a502c35e71c5c2d7b20bb","withheld":true} +{"align_key":"e3981b5b196b0b58dca390b46698520f1ba2210b3070e6c2efe2a718db1fb710","attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"fidelity":"F1","id":"ryhrskg","kind":"cell","match_hash":"e3981b5b196b0b58dca390b46698520f1ba2210b3070e6c2efe2a718db1fb710","node_hash":"137e5c7656c9add71d21b637bd2d3478be7dc4cf265f9c2d6f4251b25d148cfa","ord":4,"own_hash":"21a3bbca2a0eb2d377475067ccd1f8af53fc888a45e9ea09b0dd2227a9eaa0ef","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"e3981b5b196b0b58dca390b46698520f1ba2210b3070e6c2efe2a718db1fb710","withheld":true} +{"align_key":"35e9f434665be894a225284b4d0d885654d25aedf08294825d1b76907b75a672","id":"p5y2rec","kind":"table-note","match_hash":"a900cf7167a2ad6d9e2f58c7570ec8511d4c1492d4c7d0eda9bddb9ee0201d18","node_hash":"603da0a3034de1fb124c9964e1c85ec08f1000e96b20c3897dfb7370ad16c0b4","ord":3,"own_hash":"13c64919791af4c88c246e5c9b6e2d4e08a3439f2b148a5b4a256b42cc2dc89d","parent":"hj4s7pb","text_hash":"a900cf7167a2ad6d9e2f58c7570ec8511d4c1492d4c7d0eda9bddb9ee0201d18"} +{"align_key":"35e9f434665be894a225284b4d0d885654d25aedf08294825d1b76907b75a672","fidelity":"F2","id":"f44s64g","kind":"sentence","match_hash":"a900cf7167a2ad6d9e2f58c7570ec8511d4c1492d4c7d0eda9bddb9ee0201d18","node_hash":"c56f3db4fc673c7ebfdf91732fd34fe10a6b366f7ee7b5f3055d414fffd4a0ae","ord":0,"own_hash":"6cc40c400bf1e9021de44df93d2625bd58919cf4bd73d92e46a545fa0efae4a2","parent":"p5y2rec","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"a900cf7167a2ad6d9e2f58c7570ec8511d4c1492d4c7d0eda9bddb9ee0201d18","withheld":true} +{"align_key":"7ec1584c022460adc4cd678911d05215d17eb903cec99bbaa3017b6d1cf39065","id":"ft0jp0z","kind":"back","match_hash":"1d9bd9c89067494eca69286aca7deaa413a2717fa706d34c90e7eaef11fb8bf5","node_hash":"e2615256a87805b000c61f60e8e72010cf6f34619845c43479d5f106c3d95f75","ord":3,"own_hash":"3563f8a3c3f6f2f6e63d39877ef5ea64e2a597f719fbcab5abab127a1655d133","parent":"xxqgpzr","text_hash":"558a318476c516b1dc400894cc8be6e112b174063eaffb3e23fa8cad73543512"} +{"align_key":"7ec1584c022460adc4cd678911d05215d17eb903cec99bbaa3017b6d1cf39065","id":"hges40x","kind":"references","match_hash":"1d9bd9c89067494eca69286aca7deaa413a2717fa706d34c90e7eaef11fb8bf5","node_hash":"552d6c412bdc29d3103cea74439b5668a5736f0d5ad1be92d3b576f95984620d","ord":0,"own_hash":"b1cda0e3e3e4a636ce64cc68401738a66304e4f7e9bdf98549d8a7b926ce635d","parent":"ft0jp0z","text_hash":"558a318476c516b1dc400894cc8be6e112b174063eaffb3e23fa8cad73543512"} +{"align_key":"54e1fa11397e8dbf6bb06d6321142db9e8f2a9c7357666545a8ffa1940396a5c","fidelity":"F2","id":"tb6syqq","kind":"reference","label":"1","match_hash":"c8d11b02f745adb0f3fb4dd7343487c4b00cac7ff93bb250f6923919bc826366","node_hash":"6a85c1af0830b0fd5a50c1974029bd738cfbb0a408362e4f16774a9620d5a976","ord":0,"own_hash":"4404e35914088b5a08f94137aa6fc4a9d7fb5ee60266b8ad3a6426738211f5e9","parent":"hges40x","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"4ca0d559ff4af786781bb66a0d0fd7fd6258733cba67eba25e1d952ea305b795","withheld":true} +{"align_key":"57d76803ae8032cdbcc1af328e8e7828be0544c0c6a16fa3a5d189ad35bdc5ee","fidelity":"F2","id":"vxsdvzq","kind":"reference","label":"2","match_hash":"2946d22dfab55f8c9b9873e969f854aeb971d4fb86d44307f7a0a0a5b145aae8","node_hash":"2284a1f49e8fb21920dfe9e4f9aac853bb1bf23a4a646294e0b9a21398057cbf","ord":1,"own_hash":"57d8136e4c75c5de396fcca60fb33867b521ca0446f39a5e3f013d6c1400cfe7","parent":"hges40x","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"4fa42dcdde3e18856234dea703a429adb87ba449bae3250eeb49efea59d43935","withheld":true} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/pages.jsonl b/fixtures/packages/hale2026harmonic-damb.checks-only/pages.jsonl new file mode 100644 index 0000000..dc29f0c --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/pages.jsonl @@ -0,0 +1,2 @@ +{"page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101","size":[612,792],"stamps_removed":["downloaded-via","sharing-guidelines"],"text_layer":true,"witness":"qptsanv"} +{"page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102","size":[612,792],"stamps_removed":["downloaded-via","sharing-guidelines"],"text_layer":true,"witness":"qptsanv"} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/provenance.json b/fixtures/packages/hale2026harmonic-damb.checks-only/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/references.jsonl b/fixtures/packages/hale2026harmonic-damb.checks-only/references.jsonl new file mode 100644 index 0000000..a8d5c4d --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/references.jsonl @@ -0,0 +1,2 @@ +{"label":"1","node":"tb6syqq","resolution":{"doi":"10.5555/example.ref1","type":"doi"}} +{"label":"2","node":"vxsdvzq","resolution":{"type":"none"}} diff --git a/fixtures/packages/hale2026harmonic-damb.checks-only/witnesses.json b/fixtures/packages/hale2026harmonic-damb.checks-only/witnesses.json new file mode 100644 index 0000000..737fc22 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb.checks-only/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"qptsanv","kind":"pdf","media_type":"application/pdf","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"pages":2,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834","size":482113,"text_layer":true,"version_label":"version of record"}]} diff --git a/fixtures/packages/hale2026harmonic-damb/MANIFEST.json b/fixtures/packages/hale2026harmonic-damb/MANIFEST.json new file mode 100644 index 0000000..8b3095b --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"assets/586f92512b294a1c325bfc16207771fb9acc7bb67bb206f25a429a055134056f.png","present":false,"sha256":"586f92512b294a1c325bfc16207771fb9acc7bb67bb206f25a429a055134056f","size":18213},{"path":"assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png","sha256":"a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75","size":73},{"path":"corrections.jsonl","sha256":"026b493baaecba29c15a834e29933b840f306956d377fe85f350372313cab18f","size":8310},{"path":"datasets/ds-hale-bond-params/anchors.jsonl","sha256":"cfacea27f25c0ca912b82882c1f9221b693ae6bcf91c888628b780243ba7e625","size":6046},{"path":"datasets/ds-hale-bond-params/data.csv","sha256":"dbde72e4526e469e1535b87272eb50683160b2fe7c40b7f064e6592341f754a8","size":206},{"path":"datasets/ds-hale-bond-params/datapackage.json","sha256":"d8bbf8bd7c1b0207ada817d10580e835bda3a8691ad3e14fc1910519f4341974","size":574},{"path":"derived/mathml.jsonl","sha256":"47981f878391f3c733072081a0f6d1ad59ba8fa37507c8a4d774feb780c7df6c","size":348},{"path":"document.json","sha256":"f9d3fd85dec8b32378be5b045d0734ec05f3745ec88737bd0554749290e2fbbd","size":1088},{"path":"ids.jsonl","sha256":"d19c4716a605352d4cd84f81381d99a5e2db6b59c88e926611dd13a5a16e4155","size":852},{"path":"locations.jsonl","sha256":"37a3f73ff3dc81082e98b4a02afff535fbdf0f1439cf56fdb39566d28076c6e2","size":7396},{"path":"nodes.jsonl","sha256":"87eeac4b781f67872da36f44f74b859fe5a7c528e3c46276ec0b7dd4f5e2cb71","size":45649},{"path":"pages.jsonl","sha256":"948177c6b7e5e361ac1da0ecff6b52406d3513f14d58cd27cd84f17e6f1c054e","size":438},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"da6a4d9cf8af852dff7a175585867d6f2a224c664bd2935f4d47733cb76d1f5d","size":13150},{"path":"references.jsonl","sha256":"25c7a54848e0c3167475236846b85bcea1a35698f6ae5b24a31b6a3690078697","size":567},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"99ae654df4fb461a424bb51edd476a89041182c7df9c98653a81b78031f92ada","size":1006}],"format":"scienting-package/1","key":"hale2026harmonic-damb"} diff --git a/fixtures/packages/hale2026harmonic-damb/assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png b/fixtures/packages/hale2026harmonic-damb/assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png new file mode 100644 index 0000000..9adf6a8 Binary files /dev/null and b/fixtures/packages/hale2026harmonic-damb/assets/a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75.png differ diff --git a/fixtures/packages/hale2026harmonic-damb/corrections.jsonl b/fixtures/packages/hale2026harmonic-damb/corrections.jsonl new file mode 100644 index 0000000..6731e24 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/corrections.jsonl @@ -0,0 +1,12 @@ +{"after":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","at":"2026-10-02T10:00:00Z","author":{"key":"ana"},"before":"7252bb19f33a3be672d74a8aa8323750311b5c7d2b8f6cf21e07f17f2b27f3a1","evidence":[{"kind":"crop","sha256":"bdbf7a4d9e86609675e3fc124c21ce808053a52d6bc0f35b15e1ba39027f13af"}],"find":"3l0.0","format":"scienting-correction/1","id":"vkvk912tasd80","index":1,"op":"replace","path":["xxqgpzr","d400rz3","hj4s7pb","dwwm2fa","g8d2pjb"],"reason":"OCR read the digit 1 as the letter l.","replace":"310.0","target":"c20cna6","touched":["c20cna6"]} +{"after":"1ff0b6ee4dd92e75429d9ffc9de08656bae198b39e950d9520005d2e741ee12f","at":"2026-10-02T10:01:00Z","author":{"key":"ana"},"before":"b3438d99a16eb6944e032b4413b9153d353465dd351103cee6549c71c0221ee7","evidence":[{"kind":"crop","sha256":"321a926653b9e097987d255d9286880893d71abf895d73f1649403ed9ac0877d"}],"find":"10-3","format":"scienting-correction/1","id":"va54bce6kgvq0","index":2,"op":"replace","path":["xxqgpzr","p36k8t6","v7q07ne"],"reason":"The reading lost the superscript.","replace":[{"kind":"text","text":"10"},{"kind":"text","style":["sup"],"text":"−3"}],"target":"ec5jc93","touched":["ec5jc93"]} +{"after":"5421e9cf0ef3a995792963d0371b79e11a8efad519b02efb5cb88311a896d0cc","at":"2026-10-02T10:02:00Z","author":{"key":"ana"},"before":"1ff0b6ee4dd92e75429d9ffc9de08656bae198b39e950d9520005d2e741ee12f","created":["a4jrz2t"],"evidence":[{"by":"ana","kind":"person","note":"Read against the page."}],"format":"scienting-correction/1","id":"m824p8vy7nrx8","index":3,"offset":51,"op":"split","path":["xxqgpzr","p36k8t6","v7q07ne"],"reason":"A missed sentence boundary.","target":"ec5jc93","touched":["a4jrz2t","ec5jc93"]} +{"after":"42b1de7852cdc68730984fff789fe248ecd5b43198c0e7d671931ff3fe561dc3","at":"2026-10-02T10:03:00Z","author":{"key":"ana"},"before":"3079439be34114fc362723e64df1e2fb4a048c9e9892d6242a2c175eb28d778f","evidence":[{"by":"ana","kind":"person","note":"Read against the page."}],"format":"scienting-correction/1","id":"dzmfs6cyf89bt","index":4,"joiner":" ","op":"merge","path":["xxqgpzr","d400rz3","gwzbj3s"],"reason":"A false boundary at a line break.","retired":["ayea71r"],"target":"xjns57z","touched":["ayea71r","xjns57z"],"with":"ayea71r"} +{"after":"ff27c79f4138e71ef9fccdaab2cea2bcc7db17b7d75e2c806252a14bba9ce530","at":"2026-10-02T10:03:30Z","author":{"key":"ana"},"before":"df6e2a602ca59986c9c19dcdecf9b42da288dd3fed19a324159ce76626c80ff1","evidence":[{"by":"ana","kind":"person","note":"Read against the page."}],"format":"scienting-correction/1","id":"m4kckv7dqkjw8","index":5,"op":"merge","path":["xxqgpzr","d400rz3"],"reason":"A paragraph split at a column break.","retired":["ncx2v4f"],"target":"gwzbj3s","touched":["qwgfg51"],"with":"ncx2v4f"} +{"after":null,"at":"2026-10-02T10:04:00Z","author":{"key":"ana"},"before":"17e9ffb66c9649be9ce1052ecbc2e80dd67c2ed6cd6d4a90e06386c35676f751","evidence":[{"kind":"crop","sha256":"c5a725580e46d17c878ea2310030902f875f1748cb1aa94451df021e3bd3a42a"}],"format":"scienting-correction/1","id":"v4raw31f93rqa","index":6,"op":"delete","path":["xxqgpzr","d400rz3"],"reason":"A running head read as text.","retired":["r3w6j1w","v8e4z6z"],"target":"r3w6j1w","touched":["v8e4z6z"]} +{"after":"cc0bf73dd84e298da0d36c4b363c8d2bdc9b6d5738d1923d14c4a9028dca08d6","at":"2026-10-02T10:05:00Z","author":{"key":"ana"},"before":"47227b3e48e70a28623a93f19deda7414ebeff9d04fa00522874112249f2387b","evidence":[{"kind":"crop","sha256":"5d8e205660c2c59dcaff119b5671ac11650974b5287d7d7b239a9118e9171a85"}],"format":"scienting-correction/1","from":"(l)","id":"g30d5wph3bqyy","index":7,"label":"(1)","op":"relabel","path":["xxqgpzr","p36k8t6","tgp1qey","rr20tev"],"reason":"OCR read the equation number 1 as the letter l.","target":"tkxsmts","touched":["tkxsmts"]} +{"after":null,"at":"2026-10-02T10:06:00Z","author":{"key":"ana"},"before":"3ed0be3f77cb883c3444e7738995ea6b8c13ba0007fa5ccbab3b0bf11fa3799f","evidence":[{"kind":"crop","sha256":"a0b53d6a86df45463b4160e0b2a7643b54bb4a1a0a9d8f8d1ba7885f67ce8a5f"}],"format":"scienting-correction/1","id":"s0c7mjf6x0b6v","index":8,"op":"delete","path":["xxqgpzr","d400rz3","hj4s7pb","dwwm2fa"],"reason":"Two cells were read as one; the row is replaced.","retired":["rncchma","k03dm2e","qacy341","ex460rm","w97feam"],"target":"rncchma","touched":["ex460rm","k03dm2e","qacy341","w97feam"]} +{"after":"351e5148a560d51a815193ea6c2e48e2bb88c48322159dde0b00f568ec847bee","at":"2026-10-02T10:07:00Z","author":{"key":"ana"},"before":null,"created":["kx2kz2y","avbhhey","w0gr97q","b5gd0h1","w264b74","exms5gc"],"evidence":[{"kind":"crop","sha256":"c21b3a11b1589743a0727f2633a95fc9efd0ad82159e60358836a14405ffc9fb"}],"format":"scienting-correction/1","id":"b7hjt11dfg229","index":9,"node":{"attrs":{"header_path":["a49pag5","avbhhey"]},"children":[{"attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"CT–HC"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"content":[{"kind":"text","text":"340.0"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"content":[{"kind":"text","text":"1.090"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"content":[{"kind":"text","text":"338.7"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"content":[{"kind":"text","text":"1.0900"}],"fidelity":"F1","kind":"cell"}],"kind":"row"},"op":"insert","parent":"dwwm2fa","path":["xxqgpzr","d400rz3","hj4s7pb","dwwm2fa"],"place_after":"g8d2pjb","reason":"The CT–HC row, read again from the page.","target":"kx2kz2y","touched":["avbhhey","b5gd0h1","exms5gc","w0gr97q","w264b74"]} +{"after":"185ed695187bf68abae572ce0f6ce1a002182c9c0fa1accdc0d933ea0d944751","at":"2026-10-02T10:08:00Z","author":{"key":"ana"},"before":null,"created":["ke0jxpn","yvkd7xr","jv1741a","m1p1n2g","ganq1ns","ryhrskg"],"evidence":[{"kind":"crop","sha256":"c21b3a11b1589743a0727f2633a95fc9efd0ad82159e60358836a14405ffc9fb"}],"format":"scienting-correction/1","id":"dz23scwhh30sx","index":10,"node":{"attrs":{"header_path":["a49pag5","yvkd7xr"]},"children":[{"attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"OW–HW"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"content":[{"kind":"text","text":"553.0"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"content":[{"kind":"text","text":"0.9572"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"content":[{"kind":"text","text":"548.1"}],"fidelity":"F1","kind":"cell"},{"attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"content":[{"kind":"text","text":"0.9570"}],"fidelity":"F1","kind":"cell"}],"kind":"row"},"op":"insert","parent":"dwwm2fa","path":["xxqgpzr","d400rz3","hj4s7pb","dwwm2fa"],"place_after":"kx2kz2y","reason":"The reading dropped the OW–HW row.","target":"ke0jxpn","touched":["ganq1ns","jv1741a","m1p1n2g","ryhrskg","yvkd7xr"]} +{"after":"158c8c9d7d003f3af42c202a2623f65e80111d08a77ac3c28c1b775aa9a01841","at":"2026-10-02T10:09:00Z","attr":"colspan","author":{"key":"ana"},"before":"b2dd6c0c1c5b272ff235bf516de3aa3d51bd218ca5f947de07ae00b51fa8c337","evidence":[{"kind":"crop","sha256":"dc2f228c0312803cc1ee5626401deb540b9cf9d74404093dc33d6d7316fda655"}],"format":"scienting-correction/1","from":1,"id":"wa7sn096vxh3y","index":11,"op":"set","path":["xxqgpzr","d400rz3","hj4s7pb","nwwd4pb","nytt74z"],"reason":"Set B spans two columns.","target":"xyy7x6c","touched":["xyy7x6c"],"value":2} +{"after":"f76864779843485fa9e2f3cc3cd1c76ad222e1649c56f4cface33bf20b8f33b6","at":"2026-10-02T10:10:00Z","author":{"key":"ana"},"before":"dad89409c8a3108d0c17c8d1625a448c7920f50876dc68fd382a1114f56934ee","evidence":[{"kind":"crop","sha256":"46ee93d56ce440498b04920dcb02437dbb45153049fe3871e94b0c3a5c032d99"}],"format":"scienting-correction/1","from":"Figure l","id":"dx6rkj4hcm7gg","index":12,"label":"Figure 1","op":"relabel","path":["xxqgpzr","d400rz3"],"reason":"OCR read the figure number 1 as the letter l.","target":"v7cx6qs","touched":[]} diff --git a/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/anchors.jsonl b/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/anchors.jsonl new file mode 100644 index 0000000..73eed43 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/anchors.jsonl @@ -0,0 +1,12 @@ +{"anchor":{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","quote":{"exact":"310.0"},"rev":12,"store":"smithlab"},"field":"k_r","resource":"bond-parameters","row":"ct-ct-a"} +{"anchor":{"context":{"column_path":["Set A","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"ztww0g8","node_hash":"bda85639faacb77e504c891c035012602836171c009ecfd21584de4d6461ba93","own_hash":"7c3647ea9ead91019cd8cfcf4e9f2ff6fe610b68550aa9a983a8e7129fb37394","quote":{"exact":"1.526"},"rev":12,"store":"smithlab"},"field":"r_eq","resource":"bond-parameters","row":"ct-ct-a"} +{"anchor":{"context":{"column_path":["Set B","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"j6y45v6","node_hash":"00c4b92e220303ebc2bfb36aa557ac80ae4dba1675e9ed47adb82f6aeff10634","own_hash":"111d2b2cb30e3b04aff04b7de13a105a07a189d5ba97ae7d78eb7601ac99f9d9","quote":{"exact":"305.2"},"rev":12,"store":"smithlab"},"field":"k_r","resource":"bond-parameters","row":"ct-ct-b"} +{"anchor":{"context":{"column_path":["Set B","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"bnyvykm","node_hash":"13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94","own_hash":"2c4883c8937f42c190c21a096aaf473e1d35587acf796cc0380f2347aac42f15","quote":{"exact":"1.5260"},"rev":12,"store":"smithlab"},"field":"r_eq","resource":"bond-parameters","row":"ct-ct-b"} +{"anchor":{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–HC"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"w0gr97q","node_hash":"f738a008336ac59b2f1d45cda2f045dc96d34f0f1378c431ce6ff8e434feb8a7","own_hash":"334a22e06b79d0535839756bad22f7d970807084413358f079748a604e756a0c","quote":{"exact":"340.0"},"rev":12,"store":"smithlab"},"field":"k_r","resource":"bond-parameters","row":"ct-hc-a"} +{"anchor":{"context":{"column_path":["Set A","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","CT–HC"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"b5gd0h1","node_hash":"9635a750ac2acf526a4db28746fd3ed84659f4e384f5a73fef85d002b4e9308b","own_hash":"5ecf316bd05e3dc1c6c623bf7041b990d76cbd5d945ba6f0288ec035aedf958e","quote":{"exact":"1.090"},"rev":12,"store":"smithlab"},"field":"r_eq","resource":"bond-parameters","row":"ct-hc-a"} +{"anchor":{"context":{"column_path":["Set B","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–HC"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"w264b74","node_hash":"2ba9cea0f5c07ee9f7b47c5d541c85e92465709322869fb6c0d994ab61c56cad","own_hash":"8eeb86a83e082d38ac348fdf80dd141f91d2e44c96e0dfa175668816d8159353","quote":{"exact":"338.7"},"rev":12,"store":"smithlab"},"field":"k_r","resource":"bond-parameters","row":"ct-hc-b"} +{"anchor":{"context":{"column_path":["Set B","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","CT–HC"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"exms5gc","node_hash":"b7c47f8360eb7272d2ac0943e8bf1aec9d71cb4ea4e5e1d02f8acee5b430a038","own_hash":"286c8ff6b6fa3d1e15fc3fa667d58e85d388bb671314e8412f7b4d462afb059f","quote":{"exact":"1.0900"},"rev":12,"store":"smithlab"},"field":"r_eq","resource":"bond-parameters","row":"ct-hc-b"} +{"anchor":{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","OW–HW"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"jv1741a","node_hash":"f644190803b5ea36aa24738e7f168a7fdf0d05cb5123c14a814b7628dab71f1e","own_hash":"ff210890aa7588e223b18b1207d90186523fcc65b5773ec8465f52ce28e43bcb","quote":{"exact":"553.0"},"rev":12,"store":"smithlab"},"field":"k_r","resource":"bond-parameters","row":"ow-hw-a"} +{"anchor":{"context":{"column_path":["Set A","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","OW–HW"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"m1p1n2g","node_hash":"0847b5d75c2259257c3619e761c64d5571d3ca3932e96a96ee07e8ce68cc63be","own_hash":"00882d17f1baeea567a4a9a7dcfec3e9d96e70b82673303f45d42c5f16f0e00d","quote":{"exact":"0.9572"},"rev":12,"store":"smithlab"},"field":"r_eq","resource":"bond-parameters","row":"ow-hw-a"} +{"anchor":{"context":{"column_path":["Set B","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","OW–HW"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"ganq1ns","node_hash":"40d46db2088057debc3b1d5b4a3c972ff3a94fc3d5463565f98876d0927f1e67","own_hash":"2a85bdbe625ecb53c4b11d13661216b1e0caae9061460e2ced26deb6fd6a12bb","quote":{"exact":"548.1"},"rev":12,"store":"smithlab"},"field":"k_r","resource":"bond-parameters","row":"ow-hw-b"} +{"anchor":{"context":{"column_path":["Set B","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","OW–HW"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"ryhrskg","node_hash":"525583990e7871a2ba55739e8206abac2df0f19d30c86ad74f6cafdd7c3cbe25","own_hash":"3b273b0784185ea2fe56ca5b5e36c91498e77cbbb95652218be69d43e355a2c7","quote":{"exact":"0.9570"},"rev":12,"store":"smithlab"},"field":"r_eq","resource":"bond-parameters","row":"ow-hw-b"} diff --git a/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/data.csv b/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/data.csv new file mode 100644 index 0000000..a7294ca --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/data.csv @@ -0,0 +1,7 @@ +key,bond,set,k_r,r_eq +ct-ct-a,CT–CT,A,310.0,1.526 +ct-ct-b,CT–CT,B,305.2,1.5260 +ct-hc-a,CT–HC,A,340.0,1.090 +ct-hc-b,CT–HC,B,338.7,1.0900 +ow-hw-a,OW–HW,A,553.0,0.9572 +ow-hw-b,OW–HW,B,548.1,0.9570 diff --git a/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/datapackage.json b/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/datapackage.json new file mode 100644 index 0000000..207098f --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params/datapackage.json @@ -0,0 +1 @@ +{"format":"scienting-dataset/1","id":"ds-hale-bond-params","name":"hale-bond-params","resources":[{"encoding":"utf-8","format":"csv","name":"bond-parameters","origin":{"anchors":"anchors.jsonl","kind":"reported"},"path":"data.csv","schema":{"fields":[{"name":"key","type":"string"},{"name":"bond","type":"string"},{"name":"set","type":"string"},{"name":"k_r","type":"number","unit":"kcal / mol / angstrom ** 2"},{"name":"r_eq","type":"number","uncertainty":{"kind":"unknown"},"unit":"angstrom"}],"primaryKey":"key"}}],"title":"Harmonic bond parameters reported in Table 1"} diff --git a/fixtures/packages/hale2026harmonic-damb/derived/mathml.jsonl b/fixtures/packages/hale2026harmonic-damb/derived/mathml.jsonl new file mode 100644 index 0000000..1928ed4 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/derived/mathml.jsonl @@ -0,0 +1 @@ +{"mathml":"Ebond=12Kr(r−req)2","node":"tkxsmts","run":null,"tool":{"name":"hand","version":"0"}} diff --git a/fixtures/packages/hale2026harmonic-damb/document.json b/fixtures/packages/hale2026harmonic-damb/document.json new file mode 100644 index 0000000..d389e95 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":45,"nodes":75},"fidelity":{"counts":{"F0":1,"F1":4,"F2":13,"F3":27},"lowest":"F0"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e215570ec1c660164c8b1e8012a9c7de9e98d5e508bf80ffdc2c7cd4cbb5ab0f","key":"hale2026harmonic-damb","kind":"article","language":"en","license":{"text":"All rights reserved by the publisher (fictional)."},"meta":{"DOI":"10.5555/example.hale.2026","author":[{"family":"Hale","given":"R."},{"family":"Osei","given":"M."}],"container-title":"Journal of Example Chemistry","issued":{"date-parts":[[2026,3,2]]},"page":"101-109","title":"Harmonic bond parameters for small organic molecules from a two-step fit","type":"article-journal","volume":"14"},"meta_hash":"160ae3e2d6e2816b04c7e067d7e89e89af0bc7d0ff1ae1e6947008ea43c11e22","policy":"full","relations":[],"rev":12,"root":"66c911f82e8d7dbead030d56d0f605bb8f0c03d13ea71de48b74d6d8ebad2260","store":"smithlab","version":{"date":"2026-03-02","type":"version-of-record"},"work":{"key":"hale2026harmonic-damb","same_as":["doi:10.5555/example.hale.2026"]}} diff --git a/fixtures/packages/hale2026harmonic-damb/ids.jsonl b/fixtures/packages/hale2026harmonic-damb/ids.jsonl new file mode 100644 index 0000000..9fee9f9 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/ids.jsonl @@ -0,0 +1,11 @@ +{"id":"b-p01-text-003","kind":"alias","successor":"hca6dc5"} +{"id":"b-p02-table-001","kind":"alias","successor":"hj4s7pb"} +{"id":"ayea71r","kind":"retired","node_kind":"sentence","rev":4,"successor":"xjns57z"} +{"id":"ncx2v4f","kind":"retired","node_kind":"paragraph","rev":5,"successor":"gwzbj3s"} +{"id":"r3w6j1w","kind":"retired","node_kind":"paragraph","rev":6,"successor":null} +{"id":"v8e4z6z","kind":"retired","node_kind":"sentence","rev":6,"successor":null} +{"id":"ex460rm","kind":"retired","node_kind":"cell","rev":8,"successor":null} +{"id":"k03dm2e","kind":"retired","node_kind":"cell","rev":8,"successor":null} +{"id":"qacy341","kind":"retired","node_kind":"cell","rev":8,"successor":null} +{"id":"rncchma","kind":"retired","node_kind":"row","rev":8,"successor":null} +{"id":"w97feam","kind":"retired","node_kind":"cell","rev":8,"successor":null} diff --git a/fixtures/packages/hale2026harmonic-damb/locations.jsonl b/fixtures/packages/hale2026harmonic-damb/locations.jsonl new file mode 100644 index 0000000..b0a0961 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/locations.jsonl @@ -0,0 +1,46 @@ +{"boxes":[[72,72,493.2,83.8]],"node":"mhkp90t","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,85.95,183.15,97.75]],"node":"s1b3bjf","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,99.9,540,111.7],[72,113.85,270.9,125.65]],"node":"mhp0at8","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,127.8,405.45,139.6]],"node":"v3063qv","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,141.75,142.2,153.55]],"node":"wrxng89","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,155.7,540,167.5],[72,169.65,218.25,181.45]],"node":"kea5026","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,183.6,540,195.4],[72,197.55,540,209.35],[72,211.5,183.15,223.3]],"node":"rr20tev","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,225.45,540,237.25],[72,239.4,83.7,251.2]],"node":"hca6dc5","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,253.35,364.5,265.15]],"node":"ec5jc93","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,267.3,417.15,279.1]],"node":"a4jrz2t","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,72,112.95,83.8]],"node":"y65m5cd","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,85.95,540,97.75],[72,99.9,229.95,111.7]],"node":"xjns57z","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,113.85,376.2,125.65]],"node":"qwgfg51","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,127.8,306,139.6]],"node":"vya7t4n","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,141.75,300,291.75]],"node":"rzxn46v","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,301.75,300,451.75]],"node":"cx816pa","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,461.75,329.4,473.55]],"node":"z86b2za","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,475.7,148.05,487.5]],"node":"caehhp6","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,489.65,235.8,501.45]],"node":"nms5qjg","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,503.6,259.2,515.4]],"node":"wxxhb3s","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,517.55,95.4,529.35]],"node":"hshknn3","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,531.5,101.25,543.3]],"node":"mb6xd86","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,545.45,101.25,557.25]],"node":"xyy7x6c","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,559.4,200.7,571.2]],"node":"ycwgbx1","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,573.35,183.15,585.15]],"node":"d1mhw8b","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,587.3,200.7,599.1]],"node":"k6a6616","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,601.25,183.15,613.05]],"node":"x3ns64d","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,615.2,159.75,627]],"node":"a49pag5","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,629.15,101.25,640.95]],"node":"vd76637","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,643.1,101.25,654.9]],"node":"c20cna6","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,657.05,101.25,668.85]],"node":"ztww0g8","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,671,101.25,682.8]],"node":"j6y45v6","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,684.95,107.1,696.75]],"node":"bnyvykm","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,281.25,101.25,293.05]],"node":"avbhhey","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,295.2,101.25,307]],"node":"w0gr97q","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,309.15,101.25,320.95]],"node":"b5gd0h1","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,323.1,101.25,334.9]],"node":"w264b74","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,337.05,107.1,348.85]],"node":"exms5gc","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,351,101.25,362.8]],"node":"yvkd7xr","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,364.95,101.25,376.75]],"node":"jv1741a","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,378.9,107.1,390.7]],"node":"m1p1n2g","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,392.85,101.25,404.65]],"node":"ganq1ns","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,406.8,107.1,418.6]],"node":"ryhrskg","page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101"} +{"boxes":[[72,698.9,323.55,710.7]],"node":"f44s64g","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,712.85,446.4,724.65]],"node":"tb6syqq","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} +{"boxes":[[72,726.8,370.35,738.6]],"node":"vxsdvzq","page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102"} diff --git a/fixtures/packages/hale2026harmonic-damb/nodes.jsonl b/fixtures/packages/hale2026harmonic-damb/nodes.jsonl new file mode 100644 index 0000000..b2c5f07 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/nodes.jsonl @@ -0,0 +1,75 @@ +{"align_key":"a1a2c0fc7fbf63e304cb4b9ff28a68dc816144d21c7fd10a51a9b9b3636888af","id":"xxqgpzr","kind":"document","match_hash":"56c0a1f657bd12238d41973f5fc50ac21f3ba3c7edf5642d9d2a1c66b872cc46","node_hash":"66c911f82e8d7dbead030d56d0f605bb8f0c03d13ea71de48b74d6d8ebad2260","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"c8416875ece1042344c0aa938ccc599f21c02ef942ce96e0b6622c2869c87318"} +{"align_key":"3b69d9d8cb745638907669e2a113cfde1bc4f9a605576b8c8409426ca6b952db","id":"n5qsc9k","kind":"front","match_hash":"2b9b4ac80fbe9a8ed1d285464711e879ae8048969c2d5e83b5641363a8bd5f70","node_hash":"5a6d7f65c349ca0465e94ffc2598aae214a9377c524808cc64a8ff45a93bce38","ord":0,"own_hash":"0167516d70e0a89263e33c0f9be5ca4443113347814530257a60d43910af71b6","parent":"xxqgpzr","text_hash":"2b9b4ac80fbe9a8ed1d285464711e879ae8048969c2d5e83b5641363a8bd5f70"} +{"align_key":"22b7a9bb89f3d25de566d3c74592948c149f684f844aa9c484de3cdd89c3405b","id":"cgah0gr","kind":"title","match_hash":"c228084e30d9f8bce0a7740aa2c2fe38bdf734bda39d313029caf3704715d4a4","node_hash":"d47dc0c86131e5b6f22d9c205fd9e55ec6a8a6e0e3c2414e805710f8a825423f","ord":0,"own_hash":"c22e4fc822618a3a2c774cc9ea6fc5fc5b34463724257cfa4fd33022d4e35165","parent":"n5qsc9k","text_hash":"c228084e30d9f8bce0a7740aa2c2fe38bdf734bda39d313029caf3704715d4a4"} +{"align_key":"22b7a9bb89f3d25de566d3c74592948c149f684f844aa9c484de3cdd89c3405b","content":[{"kind":"text","text":"Harmonic bond parameters for small organic molecules from a two-step fit"}],"fidelity":"F2","id":"mhkp90t","kind":"sentence","match_hash":"c228084e30d9f8bce0a7740aa2c2fe38bdf734bda39d313029caf3704715d4a4","node_hash":"8bc4a59cae468a198e00d295e2da4930d3a77930f08bab88f035025b3b87126f","ord":0,"own_hash":"89a7fdaeb633e67eeef5a0d889d871aff66e5b6efeffe3e7107389909fc51609","parent":"cgah0gr","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"c228084e30d9f8bce0a7740aa2c2fe38bdf734bda39d313029caf3704715d4a4"} +{"align_key":"093255025a6c5844fdce4ca9ed6162c631e72259289630b3eb8b1c8fbad69569","content":[{"kind":"text","text":"R. Hale and M. Osei"}],"fidelity":"F2","id":"s1b3bjf","kind":"authors","match_hash":"73a4ad97bf47125667c5964055ccedb59eafddd3331f788efba9a42189e49726","node_hash":"b714c3d7d712d498c87047e31abdb14e90fd688aebf8fcea7dbc7b85c13b98d8","ord":1,"own_hash":"7a97d47992bcd4be203d59c30c8938650be47d92ce7f7a520a50f31d240de68b","parent":"n5qsc9k","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"73a4ad97bf47125667c5964055ccedb59eafddd3331f788efba9a42189e49726"} +{"align_key":"1e43556d60d50c9bd684876d4543b5bf37d9e14d9d75e3324ea7626231fdcfba","id":"xm3zcy9","kind":"abstract","match_hash":"4e9cd0c0fb23c926789330bd145bad542b3f245a05d3c3ffc6f79d832431b87a","node_hash":"4629f87ecb7aa5fc38a01589be0c05435b25f60d2aa502085873be021647ee3e","ord":2,"own_hash":"2266bdba2a12287fd87e9811c78be31b7286b9a429070282faf00438e3d52545","parent":"n5qsc9k","text_hash":"4e9cd0c0fb23c926789330bd145bad542b3f245a05d3c3ffc6f79d832431b87a"} +{"align_key":"1e43556d60d50c9bd684876d4543b5bf37d9e14d9d75e3324ea7626231fdcfba","id":"vcmfvx9","kind":"paragraph","match_hash":"4e9cd0c0fb23c926789330bd145bad542b3f245a05d3c3ffc6f79d832431b87a","node_hash":"1949b6dca4e1264c5adbe39e3c2aa94498c043063df685f50c3e28b9065db4e1","ord":0,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"xm3zcy9","text_hash":"4e9cd0c0fb23c926789330bd145bad542b3f245a05d3c3ffc6f79d832431b87a"} +{"align_key":"b0218c893c9d153c290f7c30132b051e23a2f757d84b283d1158635f03970d70","content":[{"kind":"text","text":"We fit harmonic bond constants for twelve bonds in two steps, first to a scan and then to vibrational frequencies."}],"fidelity":"F2","id":"mhp0at8","kind":"sentence","match_hash":"f86aa9a5344f3eaaebaf152a7a90edef5491ba6008458a4963b357b6d3c471c0","node_hash":"ee42c4780724a411697e3a95daf182d37c792d4689a7172f32929785d5fd968e","ord":0,"own_hash":"24cc437784bf358d639755dbf59984ad2c0c7a0e7f9448b23e965039b67f759b","parent":"vcmfvx9","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"f86aa9a5344f3eaaebaf152a7a90edef5491ba6008458a4963b357b6d3c471c0"} +{"align_key":"b37de6d7b4ca317978bfdf973df80bbd6ee2a3efb358f9e049723a43811f5c47","content":[{"kind":"text","text":"The two parameter sets agree to within 2% for every bond."}],"fidelity":"F2","id":"v3063qv","kind":"sentence","match_hash":"175bfc8867816a9761fd5bb9ffc956df6d9e7f203870961a5485fc1912cb663a","node_hash":"1a7ba9b1dee4195fdb79921410c2c0be3385efb27328fa1dc5f3722ab47d3102","ord":1,"own_hash":"61ba240c203a63ac5fed7554c5ba7ce20b3de55e77253c09c9ca7821870adde1","parent":"vcmfvx9","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"175bfc8867816a9761fd5bb9ffc956df6d9e7f203870961a5485fc1912cb663a"} +{"align_key":"b9d841a562fe7058947b56df1ac0bf3d6019b57eb38b5a5d61db43691ff7e434","attrs":{"level":1},"id":"p36k8t6","kind":"section","label":"1","match_hash":"ce240e49efdc58512d5b8486b16421397235dc552f1b7c5035b830af84d0324e","node_hash":"7ac12d9581ebd8e585cb319e35d08e2d2bc109739c851d0cf77337d1621f1189","ord":1,"own_hash":"78563e96f51db1954d3fabe08f3748956b564c87ba4c8f7954bf747545a37fcd","parent":"xxqgpzr","text_hash":"689bc21df84f44bd459302924e8319f6de7878e708eec28df071af73ebb3c7f2"} +{"align_key":"d3db5338aae140c5cc04ac37690aa4f98041e14a042bc6473d54ecda8d95f93e","id":"j8rdzk6","kind":"heading","match_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e","node_hash":"c7288f33d2cb2ac9b9c146dabd403d2e64e793418bd31ac14802349543ac84c8","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"p36k8t6","text_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e"} +{"align_key":"d3db5338aae140c5cc04ac37690aa4f98041e14a042bc6473d54ecda8d95f93e","content":[{"kind":"text","text":"Introduction"}],"fidelity":"F2","id":"wrxng89","kind":"sentence","match_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e","node_hash":"8a2293448ea48f2d3e279e609965f34443fae62b24b6fa13524f14a324749285","ord":0,"own_hash":"7c40e5ddd02d461a4ee50cde05532932e1d737ab3bc74b722cecf16cc6ffe59b","parent":"j8rdzk6","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e"} +{"align_key":"a547a0eeba5b2c4ae4bbd0ef9558c8a3e5f17d3915b289e7eae71385876d201e","id":"tgp1qey","kind":"paragraph","match_hash":"279a5b65251c77707a1de08eda95a800cc2c52372521c31c99d36518ac31f13f","node_hash":"107c312588366cda7106e97f4ba67b9f3f417a2f0309e46d4d2e2513fe7be3c2","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"p36k8t6","text_hash":"5a3c9e209e1a34b27aa0572f5337bd558a9cef1a0772f8e3f767bef241629bff"} +{"align_key":"e656937a809a1fe1c2513b9b4401940af910f9b0c39b6f7765c8066a5e2e5927","content":[{"kind":"text","text":"Harmonic bond terms remain the most common description of covalent stretching in classical force fields."},{"kind":"cite","refs":["tb6syqq"],"text":"1"}],"fidelity":"F2","id":"kea5026","kind":"sentence","match_hash":"83edd3a8c2b7d55b524ec0668beb74cceb3dcfb24dae5ff24e99d4c7b498e29a","node_hash":"b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33","ord":0,"own_hash":"d673d236c03d9583ecf6e01fa819765ec324dc684bd9bbc6967fa50f216e34d2","parent":"tgp1qey","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"cb8c62294f3d2fc46c3179120e278ea14537d3a03a71ce91f9e14292390aed6a"} +{"align_key":"d44bbaee84b5281067606dab69dc1e7544102aaa209fde6883063b1b6e3b60cf","content":[{"kind":"text","text":"The bond energy is given by "},{"kind":"equation","node":"tkxsmts"},{"kind":"text","text":" where "},{"kind":"math","notation":"tex","source":"K_r"},{"kind":"text","text":" is the bond force constant and "},{"kind":"math","notation":"tex","source":"r_\\mathrm{eq}"},{"kind":"text","text":" the equilibrium bond length."}],"fidelity":"F2","id":"rr20tev","kind":"sentence","match_hash":"924426976d176b8b8bb6a166c9f18d9c52225b47c1f5e17b68f0a36326f721d0","node_hash":"76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7","ord":1,"own_hash":"2d7df7b8b233eab6f96d5db0d29c99062aaa94b55cf4e388c49b9995ce7548d5","parent":"tgp1qey","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"9fe940c55192dc3d20334cd83e3213b9756b505d801289ed19f861daafb735bc"} +{"align_key":"cd2822e88bcde089a4b8d4d60820a4c0c387d75c7fb1737b5e5ac93129194ff7","content":{"notation":"tex","source":"E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2"},"fidelity":"F1","id":"tkxsmts","kind":"equation","label":"(1)","match_hash":"cd2822e88bcde089a4b8d4d60820a4c0c387d75c7fb1737b5e5ac93129194ff7","node_hash":"cc0bf73dd84e298da0d36c4b363c8d2bdc9b6d5738d1923d14c4a9028dca08d6","ord":0,"own_hash":"9caa95636262b1bd49b71e583522c8bb168d68a2beb117df34a89935eb43c6bb","parent":"rr20tev","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"b782ddc65012467b76570650ba5fdd85abac59ffa4705757439a3e5fd18c49ed"} +{"align_key":"b312865b43ddb85f757e7f1ccd66c9ffecd792742101b1659ee0b51d6f0a1d40","content":[{"kind":"text","text":"Water, H"},{"kind":"math","notation":"tex","source":"_2"},{"kind":"text","text":"O, served as the first test case, with a bending band near 1595 cm⁻¹."},{"kind":"cite","refs":["vxsdvzq"],"text":"2"}],"fidelity":"F2","id":"hca6dc5","kind":"sentence","match_hash":"1306aa85965bf549361dbb25337341ad6caa1645f52fbf8bf72378988318ab59","node_hash":"8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34","ord":2,"own_hash":"c270571517825ceed31ca912b80ac76203effe47f1c84f8ee8962800d0afc92f","parent":"tgp1qey","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"f407d24d2dfdfaaa10921f7fab05508b8ec36d14748f2fdbeaeabd90c0202f51"} +{"align_key":"d7e0e9f5c47025811b4ad3bd32df910c00314abc4d407dc031811a26d2849aa2","id":"v7q07ne","kind":"paragraph","match_hash":"e1c67a700f72e14aa8d12dc5fa3f0b2447a87bff4c9261e701fd002d89c60f68","node_hash":"eff8682d982786f9206f21cec81cd8d0888c27d97c6f60a2a4808a91356f4c5e","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"p36k8t6","text_hash":"7ea9d76e365b5fbc845041686519fa0a54031c958f3aaac7274c1d5e7effcc54"} +{"align_key":"018c6e4543067aef0e610858cac99332a110ec88535fb24d71dfced8490c34b4","content":[{"kind":"text","text":"Values below 10"},{"kind":"text","style":["sup"],"text":"−3"},{"kind":"text","text":" kcal mol⁻¹ were treated as zero."}],"fidelity":"F1","id":"ec5jc93","kind":"sentence","match_hash":"d86563d1a3f9a25de9cdb41704791a816d9ef61e6e577ebbfe6febe914b39ab5","node_hash":"5421e9cf0ef3a995792963d0371b79e11a8efad519b02efb5cb88311a896d0cc","ord":0,"own_hash":"0c9c218a3435c1473329aa5d1c0cf3368622c3073750dfeedfff47c39080e707","parent":"v7q07ne","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"d4ef9e30dbe782fbf1d61211a24db5d764e8f4cefe2b26d479fb415db8da6ca0"} +{"align_key":"42fcd1224932ee2bde2fdf29bd9d3ece91b6468f3d307212f3fe94d0633cab12","content":[{"kind":"xref","target":"hj4s7pb","text":"Table 1"},{"kind":"text","text":" lists the fitted constants for both parameter sets."}],"fidelity":"F0","id":"a4jrz2t","kind":"sentence","match_hash":"7029a6b96b3a725fc6d189edfc27012dd22234bdbf68092b46698059dfb195a7","node_hash":"f64c6a5040f9c773d5ac4e559b58465aeae30bba79a82fc38b14ac7b61826ba8","ord":1,"own_hash":"dde95db22e0600c8e6da72dd6701436315a786655cb74fc313a4bf574c9356ee","parent":"v7q07ne","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"ad4ae795e8bc91148355dc473acc0a380a985518c2dc288c58c4b9175db15081"} +{"align_key":"78649affde22d92c0d5e35351c186f4014f3f554c25ea959eac6f6d22a923e47","attrs":{"level":1},"id":"d400rz3","kind":"section","label":"2","match_hash":"e6d9e2277419beb27e5ffbeccbb8d663849adfa6eded8516352c8d56da85f982","node_hash":"e5a8eeb3c112f2dc3341da8f433540a3fc5a7e7f631e72c4dd36c6933aae808d","ord":2,"own_hash":"c3d50f266b05d7889c001aef16662cecd4e99ac4a2747ec331c1044e6adc8e3e","parent":"xxqgpzr","text_hash":"bf70316e3c0d12064d3fe27a5fb69588e708134d86427d549b30cdc94eb13a6b"} +{"align_key":"3f3867313a9dbfd5be4028e351d67cc7ef77f4b2e3d685104cda3352a602e9cc","id":"m27nkzr","kind":"heading","match_hash":"8696622f344183c4f73993a175acb8daa6418a5cc29099e5d2d762cba2d6f7f2","node_hash":"dd4e05433f92cd2fea175daa2e3e87691420d52bfd829842a97de98c23689f1c","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"d400rz3","text_hash":"8696622f344183c4f73993a175acb8daa6418a5cc29099e5d2d762cba2d6f7f2"} +{"align_key":"3f3867313a9dbfd5be4028e351d67cc7ef77f4b2e3d685104cda3352a602e9cc","content":[{"kind":"text","text":"Methods"}],"fidelity":"F2","id":"y65m5cd","kind":"sentence","match_hash":"8696622f344183c4f73993a175acb8daa6418a5cc29099e5d2d762cba2d6f7f2","node_hash":"0a24403245cf056ad054ceb58cee5b689103dae8abc3c37e4ea006f2e78303e9","ord":0,"own_hash":"394b43e9c17977cb482d6d41abb30a322d9e2d04e56492914771b846bd0f81ad","parent":"m27nkzr","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"8696622f344183c4f73993a175acb8daa6418a5cc29099e5d2d762cba2d6f7f2"} +{"align_key":"88f0218bc7fa6332ab82c98812d9c36f4005de070c64455b1e0be40da1d6b1f1","id":"gwzbj3s","kind":"paragraph","match_hash":"fa4cba349b2cbccd10ff1da08261abde3d6ef3d9d6c8f1983c9a75cf5339c479","node_hash":"ff27c79f4138e71ef9fccdaab2cea2bcc7db17b7d75e2c806252a14bba9ce530","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"d400rz3","text_hash":"a7d7bd2245df5fb568a3c61a65c308520564f27697d74a82545cac340332d702"} +{"align_key":"82e9d8b14a52cf1a5aaa37efa57fa18da552ee7d6628d056089201f404835348","content":[{"kind":"text","text":"Each bond was scanned in steps of 0.01 Å around its minimum, and the energies were fitted by least squares."}],"fidelity":"F0","id":"xjns57z","kind":"sentence","match_hash":"e422dd44e0ecba7048f79c087ff32841bef62a2583a343eae202c4b0025c3a98","node_hash":"42b1de7852cdc68730984fff789fe248ecd5b43198c0e7d671931ff3fe561dc3","ord":0,"own_hash":"4dc28d1ad57c74d044f87264dfbc744ae9d5e9644638db976dbc346361442486","parent":"gwzbj3s","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"e422dd44e0ecba7048f79c087ff32841bef62a2583a343eae202c4b0025c3a98"} +{"align_key":"bc80569a282804e707d50db1fd49cd402ec954aad4d53b4885b5f212df27f605","content":[{"kind":"xref","target":"v7cx6qs","text":"Figure 1"},{"kind":"text","text":" shows the scan for the C–C bond of ethane."},{"footnote":"ppvbzn0","kind":"fnmark","text":"a"}],"fidelity":"F2","id":"qwgfg51","kind":"sentence","match_hash":"a86a8326bd265e4ddc24c02c243e8a73ae33899886643be7eb61cd4e0f21ae7a","node_hash":"4a3be03766323b3c88d5b43591b0f573823b89fe582f2c3a6f0b43474685a30d","ord":1,"own_hash":"04bd6d16a9310fa00dbf5d0930f4dbaca52b6bb58e76bb3cdd348bec73a27737","parent":"gwzbj3s","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"f1f2b069fc19f2fd4f373923fe47a2b13a94cb672618429d20b6659b57d2f6fe"} +{"align_key":"869b204bb9bcf5b7b87aafa05c93b1784dc9862404dfb6285d0ada0b0e50fd95","id":"ppvbzn0","kind":"footnote","label":"a","match_hash":"f74f63bee6fdeabbb2d9283764bd16bf0980feedb13b76cb44cb9c66407a6f39","node_hash":"80e515958c6e33356c33f2e76bdf3a56e962325602a34138c0867bf2affde93b","ord":2,"own_hash":"3de37a8f24218b49fd407fff67524b8c59dd85b72fab58c06f589241cf25ec6c","parent":"d400rz3","text_hash":"f74f63bee6fdeabbb2d9283764bd16bf0980feedb13b76cb44cb9c66407a6f39"} +{"align_key":"869b204bb9bcf5b7b87aafa05c93b1784dc9862404dfb6285d0ada0b0e50fd95","content":[{"kind":"text","text":"Scans held every other coordinate fixed."}],"fidelity":"F2","id":"vya7t4n","kind":"sentence","match_hash":"f74f63bee6fdeabbb2d9283764bd16bf0980feedb13b76cb44cb9c66407a6f39","node_hash":"5e7362eb5c7cd2db425e557982083a51c2607521b6b1f73d79d98956616965df","ord":0,"own_hash":"1e72748c13a1160ac5fa4983bb9233913f131f1ee5846901349f5fdb2b21a6d2","parent":"ppvbzn0","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"f74f63bee6fdeabbb2d9283764bd16bf0980feedb13b76cb44cb9c66407a6f39"} +{"align_key":"87abd8a26b2108d49d5d33426391fb650cfb5c21e509b22129f617f5d499d9a2","id":"v7cx6qs","kind":"figure","label":"Figure 1","match_hash":"2b324f264d637015a59c112ae3d44ea333dfb4f25d2dc12063ce3feb6116f5b1","node_hash":"f76864779843485fa9e2f3cc3cd1c76ad222e1649c56f4cface33bf20b8f33b6","ord":3,"own_hash":"a1e46cb40201a17903dfd6f128db1e707b0e9f5bf45fcc32ec7ca772011edeae","parent":"d400rz3","text_hash":"2b324f264d637015a59c112ae3d44ea333dfb4f25d2dc12063ce3feb6116f5b1"} +{"align_key":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","attrs":{"crop":{"dpi":300,"media_type":"image/png","sha256":"586f92512b294a1c325bfc16207771fb9acc7bb67bb206f25a429a055134056f"},"figure_text":[{"boxes":[[90,300,140,310]],"id":"rtxzjj9","page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","role":"axis-label","text":"r (Å)"},{"boxes":[[90,300,140,310]],"id":"f31xtb6","page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","role":"axis-label","text":"E (kcal mol⁻¹)"},{"boxes":[[90,300,140,310]],"id":"d75908b","page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","role":"tick-label","text":"1.4"},{"boxes":[[90,300,140,310]],"id":"ts4s4z1","page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","role":"tick-label","text":"1.5"},{"boxes":[[90,300,140,310]],"id":"m621yn4","page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","role":"tick-label","text":"1.6"}],"image":{"media_type":"image/png","native":true,"sha256":"a18e1eb7f434c85ee180399dc55d2ee78c5ceb915c4a004c5dd0e490399d4c75"}},"id":"rzxn46v","kind":"panel","label":"a","match_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","node_hash":"72ab6d60a594c2fdcb20bcc7142bd8e83d36046ef817c61d4240a93e5523e4aa","ord":0,"own_hash":"95cd7f9ab50d8386dc3086cf45a377c1d25c6c6111e3c422b69af10b6b1828c6","parent":"v7cx6qs","text_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"} +{"align_key":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","id":"cx816pa","kind":"panel","label":"b","match_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","node_hash":"705d49f1d2721611705c4570b84df91932b1194d074d3a8d149ca6d3f7617bea","ord":1,"own_hash":"f31fac4186f3e54692f39e382dade6a9ca152c20fa46e06a2c5684a87148fbec","parent":"v7cx6qs","text_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"} +{"align_key":"87abd8a26b2108d49d5d33426391fb650cfb5c21e509b22129f617f5d499d9a2","id":"eb18hq4","kind":"caption","match_hash":"2b324f264d637015a59c112ae3d44ea333dfb4f25d2dc12063ce3feb6116f5b1","node_hash":"538146b0ad719df07dd338f86b42ef794e1d2a25ceef653b3a89abb74409134a","ord":2,"own_hash":"c3b298305f0176c12850acf7df92ec8a435ce882f353e92319e21d16967cf486","parent":"v7cx6qs","text_hash":"2b324f264d637015a59c112ae3d44ea333dfb4f25d2dc12063ce3feb6116f5b1"} +{"align_key":"a288d44157ba2a662c357c7e3a6b734c1b6dbf571b409e53b573fd7fb4b1ccb9","content":[{"kind":"text","text":"Bond energy along the C–C stretch of ethane."}],"fidelity":"F2","id":"z86b2za","kind":"sentence","match_hash":"93c0a80c1be2996d851f1749d8a924b6241dd922d34fa8b03468aa7d4ee13834","node_hash":"9a1c438b0f413d63b7e9f1ed7037cc6ad1665efd335baee2ef31d3d232c79552","ord":0,"own_hash":"4330a6ada17fa37ade21c7fff773ecb872e0ce49c8e4d0fa0f12f7b6789c157f","parent":"eb18hq4","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"93c0a80c1be2996d851f1749d8a924b6241dd922d34fa8b03468aa7d4ee13834"} +{"align_key":"cad40d8d5a604dcb41efc46de93cabad8c2e2f0d0c2a34d7a5ecaab59c989335","content":[{"kind":"text","text":"(a) The scan."}],"fidelity":"F2","id":"caehhp6","kind":"sentence","match_hash":"33619acba0c7348fb4902cce2d309177d43904fc582f73bf6940a64034fcd731","node_hash":"9f9c9a412cd08d0634daa3f23c63f5125c1270c13834c45c045c1a9a7452af86","ord":1,"own_hash":"75a68ec1ba13ad2d3fb7ef61634103b8740eb98494ca8fb607a3429f464ed278","parent":"eb18hq4","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"33619acba0c7348fb4902cce2d309177d43904fc582f73bf6940a64034fcd731"} +{"align_key":"74422d63b6e783ebba263333768c8cdc26e7d7d3341b7327454adc251c7c474a","content":[{"kind":"text","text":"(b) The residual of the fit."}],"fidelity":"F2","id":"nms5qjg","kind":"sentence","match_hash":"2dcae102f2ea78cb194e724e3ac5210727cf74e469eb36bf245191a023361cd8","node_hash":"e2f0b1d093c2f38f329c16edae255aed6e913d489e730a9d4857a3c3b5040f63","ord":2,"own_hash":"468991e7fcfde3f2da28039d7f056b3a56fbbe6140cb734126baba23a4742afc","parent":"eb18hq4","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"2dcae102f2ea78cb194e724e3ac5210727cf74e469eb36bf245191a023361cd8"} +{"align_key":"c5090ef974bbf44a9a95741ce5c181d7bc9c646d90d2ea54a97c3e084d9c4d04","attrs":{"columns":[{"header_path":["hshknn3"],"id":"kw15683"},{"header_path":["mb6xd86","ycwgbx1"],"id":"wdtrcqt"},{"header_path":["mb6xd86","d1mhw8b"],"id":"pge4yxn"},{"header_path":["xyy7x6c","k6a6616"],"id":"dh9a2te"},{"header_path":["xyy7x6c","x3ns64d"],"id":"xdk3d93"}]},"id":"hj4s7pb","kind":"table","label":"Table 1","match_hash":"47e5005e790fdc5f8d2a3e591b6fa938f6689a4aabc4158e22ebf5178117e53d","node_hash":"6c6fba200faf41cd06fa8b64e06e2aa29ff8848568b859ae42d1902596348643","ord":4,"own_hash":"66310a9ab1c92568f4c6cae012e35d4245d4ca4b89d2542b7c2113a31ad379ed","parent":"d400rz3","text_hash":"6694730560450e67ba90c083ac2a8a09b774de4dba41660d5ca18b8470066cbf"} +{"align_key":"5bf278d41bc3aa26cf7053443c52dc212328ea2e16894449550e8fd70b8ada0b","id":"dnyp9c1","kind":"caption","match_hash":"955ed4290a6d4eff250c6ce051442f5b9bc98630c4425105fe321d30d2656e39","node_hash":"199dc589742d341f29a67f5c254882c1ea3ec7462fae2cb3f79c40dd1993da75","ord":0,"own_hash":"c3b298305f0176c12850acf7df92ec8a435ce882f353e92319e21d16967cf486","parent":"hj4s7pb","text_hash":"955ed4290a6d4eff250c6ce051442f5b9bc98630c4425105fe321d30d2656e39"} +{"align_key":"5bf278d41bc3aa26cf7053443c52dc212328ea2e16894449550e8fd70b8ada0b","content":[{"kind":"text","text":"Fitted harmonic bond parameters."}],"fidelity":"F2","id":"wxxhb3s","kind":"sentence","match_hash":"955ed4290a6d4eff250c6ce051442f5b9bc98630c4425105fe321d30d2656e39","node_hash":"52063ded5cf76abdd32ba5c1d0d5d7348843eb0516ad29f5b1f249964e015b50","ord":0,"own_hash":"506d3bd0afffb1dff34f1563338d538c85be50434905c86784a94b747f979bc3","parent":"dnyp9c1","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"955ed4290a6d4eff250c6ce051442f5b9bc98630c4425105fe321d30d2656e39"} +{"align_key":"5771fec3fb2305f70a8eb06ec7386087264047efee0d7d8dbd8d25758175ebca","id":"nwwd4pb","kind":"table-head","match_hash":"4e19bd47c00e86da7e54b6eca51444ae29a8187df7f634381c169da5e4ad90fc","node_hash":"b3cc0a362841bb47bd2e06e0f7e452a452674ef146d28db31eb387fbdd749837","ord":1,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"hj4s7pb","text_hash":"e0440966783b8aeb165978ce3dc64a0018ca5be0332515cd14e57c54d9179796"} +{"align_key":"a659ad2672917045b0c527c1743ea1185b11723d1df41b292bdbb2c463171292","id":"nytt74z","kind":"row","match_hash":"6e9c9fb5f4f408cb60f8befbbaa4c636eb9f83bf68370d2a0614a9d859c0c50e","node_hash":"2d9dade4aa18c5da03757f4b7d938307d48f925971ca286e80220a3f001f2584","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"nwwd4pb","text_hash":"6e9c9fb5f4f408cb60f8befbbaa4c636eb9f83bf68370d2a0614a9d859c0c50e"} +{"align_key":"f21dea74d898cfeaf836ecc99ad0331bade09711ff927365e91ada2ff4cb5caf","attrs":{"colspan":1,"column":"kw15683","role":"column-header","rowspan":2},"content":[{"kind":"text","text":"Bond"}],"fidelity":"F1","id":"hshknn3","kind":"cell","match_hash":"8f8fd9ecdd4abade9e242bbe78dfce031a19b5ae23e5f5fa609a3f17fd17ad0e","node_hash":"bc09c4e13221dcbdeb8297fa175d183e1fdd20369846b117820e9b21a9cdc3de","ord":0,"own_hash":"c22cfd9e9a38d17e301d1c7f7d606817069beabbabbb953679c10e61ca4269c3","parent":"nytt74z","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"8f8fd9ecdd4abade9e242bbe78dfce031a19b5ae23e5f5fa609a3f17fd17ad0e"} +{"align_key":"8c8978cd7982d691c64d813efb1d4afb97acc793da3e39a68d046e2a93ae2be6","attrs":{"colspan":2,"column":"wdtrcqt","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"Set A"}],"fidelity":"F1","id":"mb6xd86","kind":"cell","match_hash":"7781d909b92b076f727912ebbbd5bc71a668b5a0addb8f63233d3c8c57845f3f","node_hash":"111dcef70910a8fe13e4a0d00c6260aac8fccd6fb1695ca03779f67e5babfee1","ord":1,"own_hash":"7164518d0e481cff273072c9ef49012d99d8a022a87b02a42430b4fedf118009","parent":"nytt74z","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"7781d909b92b076f727912ebbbd5bc71a668b5a0addb8f63233d3c8c57845f3f"} +{"align_key":"45b0a30471aa0a404b7ff95e2dcdee8826375dd82b30f0e7d4c10d53ef30f3e6","attrs":{"colspan":2,"column":"dh9a2te","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"Set B"}],"fidelity":"F1","id":"xyy7x6c","kind":"cell","match_hash":"bf8f310bda440cf1d4b84f04ac5f8a0a3c61d9265902e047dc0c7ad8c254b7f0","node_hash":"158c8c9d7d003f3af42c202a2623f65e80111d08a77ac3c28c1b775aa9a01841","ord":2,"own_hash":"cfc1afb54a88a32afd9c650492ff35f3809dc88593eee066bafa004ef3cf1874","parent":"nytt74z","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"bf8f310bda440cf1d4b84f04ac5f8a0a3c61d9265902e047dc0c7ad8c254b7f0"} +{"align_key":"9b6d6cb576d576764f7e189c1ed2aa0392ab210116039e4ee928552c6a795e32","id":"kba3nve","kind":"row","match_hash":"f8b45189d816aa3993f210c6d7f53f7362f99fe117753b902017a4e71fa4cfb7","node_hash":"6fd8c6f4ed609e69566534a107a05b23845bf47d8d0749fa16d7924a62e58e0f","ord":1,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"nwwd4pb","text_hash":"164b44e31c7b63ded18cea61033bcfdd7e41c0b9a7cfbeb646151211f4f56dd9"} +{"align_key":"30f672b6cdc284f1301ceeabeef408d01daf908ab595d94a8ccd0b1a11cc3d36","attrs":{"colspan":1,"column":"wdtrcqt","role":"column-header","rowspan":1},"content":[{"kind":"math","notation":"tex","source":"K_r"},{"kind":"text","text":" (kcal mol⁻¹ Å⁻²)"}],"fidelity":"F1","id":"ycwgbx1","kind":"cell","match_hash":"b1f176c51fe311a983d0496a84edb0888eeb983b142fb656ca2ca10f178f53c4","node_hash":"167d1551ca64cad5b1143431c5af6d3fc24530887470b7fd265df88d1f54f267","ord":0,"own_hash":"b62db4b357667e9c7dff003b25ec0339d64beef0d0133ead8d58fde8d8310dab","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"250808e334a5d40d3c8d967571e2adb4c75e9637b656054c397de8766c1c2fcb"} +{"align_key":"afcc57c89a13b80567d04a282c9f7a723a312442b9566a5ac57134a4f740f60c","attrs":{"colspan":1,"column":"pge4yxn","role":"column-header","rowspan":1},"content":[{"kind":"math","notation":"tex","source":"r_\\mathrm{eq}"},{"kind":"text","text":" (Å)"}],"fidelity":"F1","id":"d1mhw8b","kind":"cell","match_hash":"8ac8c7d949e092557499a31394ea8c2f6737072561797f2fbae9c0e36dc1cba6","node_hash":"557a47334329925d191e772172fddbc1bd1a035eb2217240c476ee6bc43c92ab","ord":1,"own_hash":"8651acc95e9c49891668e87725b2c962005c4c04d1db123bd13d09292bec005c","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"fdda118ed46f24353ac4d657707fc6fa86a9787123c7c080edeb8c20513879e3"} +{"align_key":"30f672b6cdc284f1301ceeabeef408d01daf908ab595d94a8ccd0b1a11cc3d36","attrs":{"colspan":1,"column":"dh9a2te","role":"column-header","rowspan":1},"content":[{"kind":"math","notation":"tex","source":"K_r"},{"kind":"text","text":" (kcal mol⁻¹ Å⁻²)"}],"fidelity":"F1","id":"k6a6616","kind":"cell","match_hash":"b1f176c51fe311a983d0496a84edb0888eeb983b142fb656ca2ca10f178f53c4","node_hash":"90aa63a43587bdcee8e428c7dc7a95ac1502bdbcb9f49cae05c433db6d18348b","ord":2,"own_hash":"f5b0796ed1afab9435cb1fcc24c80bc0454899b2076ffe162b69bd683dbcef2b","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"250808e334a5d40d3c8d967571e2adb4c75e9637b656054c397de8766c1c2fcb"} +{"align_key":"afcc57c89a13b80567d04a282c9f7a723a312442b9566a5ac57134a4f740f60c","attrs":{"colspan":1,"column":"xdk3d93","role":"column-header","rowspan":1},"content":[{"kind":"math","notation":"tex","source":"r_\\mathrm{eq}"},{"kind":"text","text":" (Å)"}],"fidelity":"F1","id":"x3ns64d","kind":"cell","match_hash":"8ac8c7d949e092557499a31394ea8c2f6737072561797f2fbae9c0e36dc1cba6","node_hash":"6bfc0a055148d877dbaf28b7f62565de7b6926137bf032c382282c39a4876797","ord":3,"own_hash":"c487b3d2c00526895141cfe4099bb114dbc5a4c6ce4975383a9e95551deaf7fa","parent":"kba3nve","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"fdda118ed46f24353ac4d657707fc6fa86a9787123c7c080edeb8c20513879e3"} +{"align_key":"d8a16dc017f11e5e02e5fec0422b7acad0223a9a152d8f21310eaefa6ccca895","id":"dwwm2fa","kind":"table-body","match_hash":"a477b7dda745bc0b339f1fd8599c7869ba9c91c648ba1ae42096f13949944970","node_hash":"bbc57601027c304301fce03f406b68445e00b79c38a886c5a4da8c9f217a358c","ord":2,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"hj4s7pb","text_hash":"a477b7dda745bc0b339f1fd8599c7869ba9c91c648ba1ae42096f13949944970"} +{"align_key":"41b1ca8b524b5a59eec07b0151ee5e8c02906e446d7ad0c739f179acbbbe0974","id":"re8z87t","kind":"row","match_hash":"deaa884fd6ab00c358507695e45b7f13c55c2c97cd527617be3b8b030d04631f","node_hash":"1532be8defe04948214d5e23af53cbf364ac95f6bd3dd37d91043c32cff405b0","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dwwm2fa","text_hash":"deaa884fd6ab00c358507695e45b7f13c55c2c97cd527617be3b8b030d04631f"} +{"align_key":"41b1ca8b524b5a59eec07b0151ee5e8c02906e446d7ad0c739f179acbbbe0974","attrs":{"colspan":5,"column":"kw15683","role":"row-group-header","rowspan":1},"content":[{"kind":"text","text":"Bond parameters"}],"fidelity":"F1","id":"a49pag5","kind":"cell","match_hash":"deaa884fd6ab00c358507695e45b7f13c55c2c97cd527617be3b8b030d04631f","node_hash":"280774d6425f0c95b0a52580a781cdf80728cb0bd35be93d36cbdaa6d1206a4b","ord":0,"own_hash":"809d1ed40895ecc01b869c54d6d62223fc5ce9428a92b15bbd7ad16d4c93370e","parent":"re8z87t","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"deaa884fd6ab00c358507695e45b7f13c55c2c97cd527617be3b8b030d04631f"} +{"align_key":"4a372ae875dc53180d3e26bd46ad452ca785b68e8e0d7075310def8efd012f69","attrs":{"header_path":["a49pag5","vd76637"]},"id":"g8d2pjb","kind":"row","match_hash":"cef7e16a07e0502817f2a277b0e0972066f1d80b928e72db831692dae8b8f519","node_hash":"5b3fb4e1cd577e8dfb6e4fc710f537e6a5b5e5178b6657dea49ba0cd94732851","ord":1,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dwwm2fa","text_hash":"cef7e16a07e0502817f2a277b0e0972066f1d80b928e72db831692dae8b8f519"} +{"align_key":"5d6ea91a72c2c0814444754cdb18d29539f0ef382d801c6d7184be392b35c798","attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"CT–CT"}],"fidelity":"F1","id":"vd76637","kind":"cell","match_hash":"670ae760d62ff8d674b222641915f452595b35aa53cdbd5b27194ef13c29e7f4","node_hash":"33810e4da42f8e65a224b5369c06fe8db254890294b7b6760808fe6e039da21a","ord":0,"own_hash":"2ef085ec0ae741d540d9ace389393d02c30523a66f55648470404733c73ecde3","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"670ae760d62ff8d674b222641915f452595b35aa53cdbd5b27194ef13c29e7f4"} +{"align_key":"b478fdfee29a549693a103681b3ad91c628d0f16ad0a7b2c5b089fe8ecd1f6ca","attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"content":[{"kind":"text","text":"310.0"}],"fidelity":"F1","id":"c20cna6","kind":"cell","match_hash":"b478fdfee29a549693a103681b3ad91c628d0f16ad0a7b2c5b089fe8ecd1f6ca","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","ord":1,"own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"b478fdfee29a549693a103681b3ad91c628d0f16ad0a7b2c5b089fe8ecd1f6ca"} +{"align_key":"ee8dce19ea6dd3f91de5a1b9d9c13c2077c462523d14b5cd9958749e6b58d7e6","attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"content":[{"kind":"text","text":"1.526"}],"fidelity":"F1","id":"ztww0g8","kind":"cell","match_hash":"ee8dce19ea6dd3f91de5a1b9d9c13c2077c462523d14b5cd9958749e6b58d7e6","node_hash":"bda85639faacb77e504c891c035012602836171c009ecfd21584de4d6461ba93","ord":2,"own_hash":"7c3647ea9ead91019cd8cfcf4e9f2ff6fe610b68550aa9a983a8e7129fb37394","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"ee8dce19ea6dd3f91de5a1b9d9c13c2077c462523d14b5cd9958749e6b58d7e6"} +{"align_key":"6b8d9cf3fe1a78784cab97278e5ccfdf305879dd1cd120c3fe6708b529f31b15","attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"content":[{"kind":"text","text":"305.2"}],"fidelity":"F1","id":"j6y45v6","kind":"cell","match_hash":"6b8d9cf3fe1a78784cab97278e5ccfdf305879dd1cd120c3fe6708b529f31b15","node_hash":"00c4b92e220303ebc2bfb36aa557ac80ae4dba1675e9ed47adb82f6aeff10634","ord":3,"own_hash":"111d2b2cb30e3b04aff04b7de13a105a07a189d5ba97ae7d78eb7601ac99f9d9","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"6b8d9cf3fe1a78784cab97278e5ccfdf305879dd1cd120c3fe6708b529f31b15"} +{"align_key":"c649510dde8e1cdf382f42a071e5fa75089e908840c9e8d1aa30ff514b2379e4","attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"content":[{"kind":"text","text":"1.5260"}],"fidelity":"F1","id":"bnyvykm","kind":"cell","match_hash":"c649510dde8e1cdf382f42a071e5fa75089e908840c9e8d1aa30ff514b2379e4","node_hash":"13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94","ord":4,"own_hash":"2c4883c8937f42c190c21a096aaf473e1d35587acf796cc0380f2347aac42f15","parent":"g8d2pjb","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"c649510dde8e1cdf382f42a071e5fa75089e908840c9e8d1aa30ff514b2379e4"} +{"align_key":"a45b00112a0139c2844a5212ae484918fb1ae0296afaa09a1a68dc8b239bb16d","attrs":{"header_path":["a49pag5","avbhhey"]},"id":"kx2kz2y","kind":"row","match_hash":"bbd74c08e45ad5c37ea7f49f508f61e5db84832fb8e1f1fbab93c81d7365526e","node_hash":"351e5148a560d51a815193ea6c2e48e2bb88c48322159dde0b00f568ec847bee","ord":2,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dwwm2fa","text_hash":"bbd74c08e45ad5c37ea7f49f508f61e5db84832fb8e1f1fbab93c81d7365526e"} +{"align_key":"118187fa2e09363d37d69618e281113d5d02a9ee8a702bbe9aa12a4cbeeb1390","attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"CT–HC"}],"fidelity":"F1","id":"avbhhey","kind":"cell","match_hash":"8e626647307dc064d96fb93c50b4c6c5cab90f9369f00a7252a004a0c9871ee3","node_hash":"c51730c0b1d7e11b51b317163ae42838f1be808b3690f196923482c9021f97c0","ord":0,"own_hash":"5aafdc0acc67b30942a64cb8c866186485ebce1026483a2e1ef069fb805bd3d9","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"8e626647307dc064d96fb93c50b4c6c5cab90f9369f00a7252a004a0c9871ee3"} +{"align_key":"f30130f6a42898d5d87ecd4d8503854dd79a2b6ea87b769fe994ce7f8ec52b29","attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"content":[{"kind":"text","text":"340.0"}],"fidelity":"F1","id":"w0gr97q","kind":"cell","match_hash":"f30130f6a42898d5d87ecd4d8503854dd79a2b6ea87b769fe994ce7f8ec52b29","node_hash":"f738a008336ac59b2f1d45cda2f045dc96d34f0f1378c431ce6ff8e434feb8a7","ord":1,"own_hash":"334a22e06b79d0535839756bad22f7d970807084413358f079748a604e756a0c","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"f30130f6a42898d5d87ecd4d8503854dd79a2b6ea87b769fe994ce7f8ec52b29"} +{"align_key":"1bec39b32c2e32386d9d6782efca347244c62b4c431e4dc2a55481a5da7f704d","attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"content":[{"kind":"text","text":"1.090"}],"fidelity":"F1","id":"b5gd0h1","kind":"cell","match_hash":"1bec39b32c2e32386d9d6782efca347244c62b4c431e4dc2a55481a5da7f704d","node_hash":"9635a750ac2acf526a4db28746fd3ed84659f4e384f5a73fef85d002b4e9308b","ord":2,"own_hash":"5ecf316bd05e3dc1c6c623bf7041b990d76cbd5d945ba6f0288ec035aedf958e","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"1bec39b32c2e32386d9d6782efca347244c62b4c431e4dc2a55481a5da7f704d"} +{"align_key":"b8ab64f15f3d461877b84369e57a5cf1c3540a6b69165abf0234df415a8d5cf2","attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"content":[{"kind":"text","text":"338.7"}],"fidelity":"F1","id":"w264b74","kind":"cell","match_hash":"b8ab64f15f3d461877b84369e57a5cf1c3540a6b69165abf0234df415a8d5cf2","node_hash":"2ba9cea0f5c07ee9f7b47c5d541c85e92465709322869fb6c0d994ab61c56cad","ord":3,"own_hash":"8eeb86a83e082d38ac348fdf80dd141f91d2e44c96e0dfa175668816d8159353","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"b8ab64f15f3d461877b84369e57a5cf1c3540a6b69165abf0234df415a8d5cf2"} +{"align_key":"fedc98fca86c767960acd84bda18f46890b81621a14d3a8cbfd908a652fdb30e","attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"content":[{"kind":"text","text":"1.0900"}],"fidelity":"F1","id":"exms5gc","kind":"cell","match_hash":"fedc98fca86c767960acd84bda18f46890b81621a14d3a8cbfd908a652fdb30e","node_hash":"b7c47f8360eb7272d2ac0943e8bf1aec9d71cb4ea4e5e1d02f8acee5b430a038","ord":4,"own_hash":"286c8ff6b6fa3d1e15fc3fa667d58e85d388bb671314e8412f7b4d462afb059f","parent":"kx2kz2y","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"fedc98fca86c767960acd84bda18f46890b81621a14d3a8cbfd908a652fdb30e"} +{"align_key":"283bdfbbf34f5e6fe9ca4f6ff2594fbdd6bd372c930e8319f1fe93be0ce403f1","attrs":{"header_path":["a49pag5","yvkd7xr"]},"id":"ke0jxpn","kind":"row","match_hash":"5af49b35ec3075f7ba7434abe632ab928db0fb5594fabd4de6e9a0813995a2d0","node_hash":"185ed695187bf68abae572ce0f6ce1a002182c9c0fa1accdc0d933ea0d944751","ord":3,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dwwm2fa","text_hash":"5af49b35ec3075f7ba7434abe632ab928db0fb5594fabd4de6e9a0813995a2d0"} +{"align_key":"25283c28aaea468386320dec27244cd4319a49a9f2126eb9c48c46bf36e6f0b7","attrs":{"colspan":1,"column":"kw15683","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"OW–HW"}],"fidelity":"F1","id":"yvkd7xr","kind":"cell","match_hash":"ba9b0eb1802de135cc2a35d473b340367e85d36ac8a72345c2ef6ab7e75e6881","node_hash":"aab8791a24bc4067c7e37fc5f0244d2128205e0a169e65c2c0fad977aabce313","ord":0,"own_hash":"943ff2019857c2f6dc6d5c08bb0f4423bb31a8d2fac8951e3fa79c1e2ef9a736","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"ba9b0eb1802de135cc2a35d473b340367e85d36ac8a72345c2ef6ab7e75e6881"} +{"align_key":"bb6b559fd0ec5a9acb92f206cd1cce8fbc9363c199ad10b9488878879c628918","attrs":{"colspan":1,"column":"wdtrcqt","role":"data","rowspan":1},"content":[{"kind":"text","text":"553.0"}],"fidelity":"F1","id":"jv1741a","kind":"cell","match_hash":"bb6b559fd0ec5a9acb92f206cd1cce8fbc9363c199ad10b9488878879c628918","node_hash":"f644190803b5ea36aa24738e7f168a7fdf0d05cb5123c14a814b7628dab71f1e","ord":1,"own_hash":"ff210890aa7588e223b18b1207d90186523fcc65b5773ec8465f52ce28e43bcb","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"bb6b559fd0ec5a9acb92f206cd1cce8fbc9363c199ad10b9488878879c628918"} +{"align_key":"ec3cf0aa426cd944077cc1b561183e1dd8752c9f83fa80eba92192e6bf0cb47e","attrs":{"colspan":1,"column":"pge4yxn","role":"data","rowspan":1},"content":[{"kind":"text","text":"0.9572"}],"fidelity":"F1","id":"m1p1n2g","kind":"cell","match_hash":"ec3cf0aa426cd944077cc1b561183e1dd8752c9f83fa80eba92192e6bf0cb47e","node_hash":"0847b5d75c2259257c3619e761c64d5571d3ca3932e96a96ee07e8ce68cc63be","ord":2,"own_hash":"00882d17f1baeea567a4a9a7dcfec3e9d96e70b82673303f45d42c5f16f0e00d","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"ec3cf0aa426cd944077cc1b561183e1dd8752c9f83fa80eba92192e6bf0cb47e"} +{"align_key":"19930871950bbde163c3eb53975f62fe19dd65adab1afbdd3c9a04011c868488","attrs":{"colspan":1,"column":"dh9a2te","role":"data","rowspan":1},"content":[{"kind":"text","text":"548.1"}],"fidelity":"F1","id":"ganq1ns","kind":"cell","match_hash":"19930871950bbde163c3eb53975f62fe19dd65adab1afbdd3c9a04011c868488","node_hash":"40d46db2088057debc3b1d5b4a3c972ff3a94fc3d5463565f98876d0927f1e67","ord":3,"own_hash":"2a85bdbe625ecb53c4b11d13661216b1e0caae9061460e2ced26deb6fd6a12bb","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"19930871950bbde163c3eb53975f62fe19dd65adab1afbdd3c9a04011c868488"} +{"align_key":"eb7d66cb8e1ca7f8d8430d68a5a4e4d50c76d39b81993775fb5e944b003c390a","attrs":{"colspan":1,"column":"xdk3d93","role":"data","rowspan":1},"content":[{"kind":"text","text":"0.9570"}],"fidelity":"F1","id":"ryhrskg","kind":"cell","match_hash":"eb7d66cb8e1ca7f8d8430d68a5a4e4d50c76d39b81993775fb5e944b003c390a","node_hash":"525583990e7871a2ba55739e8206abac2df0f19d30c86ad74f6cafdd7c3cbe25","ord":4,"own_hash":"3b273b0784185ea2fe56ca5b5e36c91498e77cbbb95652218be69d43e355a2c7","parent":"ke0jxpn","prov":{"backend":"docling (illustrative)","witnesses":["qptsanv"]},"text_hash":"eb7d66cb8e1ca7f8d8430d68a5a4e4d50c76d39b81993775fb5e944b003c390a"} +{"align_key":"6570a6f13ac110080144a56e087ad15832c104d0e4035dd0d4a2fb17a7af7783","id":"p5y2rec","kind":"table-note","match_hash":"a877cef7ab5748aa219bbcc8916dd4e58d20cb8f77c503cab33c0e6de623ef42","node_hash":"d341fed063b8cedd2929332cfd4e20fada8bc3e21c1765b13f60c28b3ab99b7b","ord":3,"own_hash":"606bedb4bbe285b916ed03d2667874614f1a742a4dd96fcff0847a2cda82233c","parent":"hj4s7pb","text_hash":"a877cef7ab5748aa219bbcc8916dd4e58d20cb8f77c503cab33c0e6de623ef42"} +{"align_key":"6570a6f13ac110080144a56e087ad15832c104d0e4035dd0d4a2fb17a7af7783","content":[{"kind":"text","text":"Set B was refitted with half the step size."}],"fidelity":"F2","id":"f44s64g","kind":"sentence","match_hash":"a877cef7ab5748aa219bbcc8916dd4e58d20cb8f77c503cab33c0e6de623ef42","node_hash":"21684f7260cb72cfe184a8c9ca42084436b38d6dedd341ae0cf5f248a76a66c8","ord":0,"own_hash":"e458a50764e270e5911a763774b6982886847a4e7720f61f21a635d3e457abeb","parent":"p5y2rec","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"a877cef7ab5748aa219bbcc8916dd4e58d20cb8f77c503cab33c0e6de623ef42"} +{"align_key":"85c6f14b0fafd29a171abf9b19ae30c7cb3190380aedc8888c176914af0981e6","id":"ft0jp0z","kind":"back","match_hash":"ca900096b5bb9658fa9a9dbecfb5397b4fa406736d4d25b1e1b1604538061358","node_hash":"49cf247605d22ef7c8a188deee10c50e8eabda9790518d1c494b24d01126ad06","ord":3,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"xxqgpzr","text_hash":"a9b95f9e1bd8a36fd83522c839870d36f5accbf5c5c97a506f706b50b231c26c"} +{"align_key":"85c6f14b0fafd29a171abf9b19ae30c7cb3190380aedc8888c176914af0981e6","id":"hges40x","kind":"references","match_hash":"ca900096b5bb9658fa9a9dbecfb5397b4fa406736d4d25b1e1b1604538061358","node_hash":"3d92aa57d6349a80b4a644eb4d9593eb693bb11e1c464c548e01be859139e7bb","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"ft0jp0z","text_hash":"a9b95f9e1bd8a36fd83522c839870d36f5accbf5c5c97a506f706b50b231c26c"} +{"align_key":"d608bdc8e8007bd4e4d25290e35d37c61c93e4f77b9edddbcbfd4599e43731f5","content":[{"kind":"text","text":"(1) A. Author and B. Author, J. Example Chem. 2001, 12, 345–350."}],"fidelity":"F2","id":"tb6syqq","kind":"reference","label":"1","match_hash":"d48a330a25fccfdda363da51e3c68643e5ff1fd3e51cd61ee573341d0bbfceda","node_hash":"442dfa9dcf19c75f9c14cae4c983eb57e65f7a35c9dde080084d86ed088dd1fb","ord":0,"own_hash":"789d899112bf2ac74569b68ef18a1467ef9dd2ac78411df5826820bd559c20bf","parent":"hges40x","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"807acc045a31ceea788b808e19dfeb65a63128a6f8b7c5bdac9bf5b8666c95b0"} +{"align_key":"86123b3bf328b71716e568fc389bdec8be999144adf7b12dd488fdd203d466cc","content":[{"kind":"text","text":"(2) C. Writer, Example Spectroscopy 2010, 7, 89–97."}],"fidelity":"F2","id":"vxsdvzq","kind":"reference","label":"2","match_hash":"2262a041e97da4d2f93423922c43671d613411556a783a0f68df7772a6e6a1a9","node_hash":"55f14a794d6629a439c3faeb60f51aa130c78018ff85f83e1b524e3f2bae490f","ord":1,"own_hash":"e40c89a96d003d5aa0299bf2a9abdff3e5cd23c0ce6341e3187657bab765da06","parent":"hges40x","prov":{"backend":"docling (illustrative)","corroborated_by":["qptsanv"],"witnesses":["qptsanv"]},"text_hash":"48b09f2dd83a6db28d8557eca54357536093c590bbe22f0a805407b3574f6353"} diff --git a/fixtures/packages/hale2026harmonic-damb/pages.jsonl b/fixtures/packages/hale2026harmonic-damb/pages.jsonl new file mode 100644 index 0000000..dc29f0c --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/pages.jsonl @@ -0,0 +1,2 @@ +{"page":1,"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","page_label":"101","size":[612,792],"stamps_removed":["downloaded-via","sharing-guidelines"],"text_layer":true,"witness":"qptsanv"} +{"page":2,"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","page_label":"102","size":[612,792],"stamps_removed":["downloaded-via","sharing-guidelines"],"text_layer":true,"witness":"qptsanv"} diff --git a/fixtures/packages/hale2026harmonic-damb/provenance.json b/fixtures/packages/hale2026harmonic-damb/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/packages/hale2026harmonic-damb/receipts.jsonl b/fixtures/packages/hale2026harmonic-damb/receipts.jsonl new file mode 100644 index 0000000..d0d8814 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/receipts.jsonl @@ -0,0 +1,8 @@ +{"at":"2026-10-01T16:00:00Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"bnyvykm","sha256":"2c560caeaf914f3521fd0e3fca433922fcb9408c184c9b72bcfa869adf5ed409"},{"kind":"crop","node":"c20cna6","sha256":"bdbf7a4d9e86609675e3fc124c21ce808053a52d6bc0f35b15e1ba39027f13af"},{"kind":"crop","node":"ztww0g8","sha256":"902e8ca35e1a313a81130c4c100aeb2233fd53854677b3a992fb16f744fe3151"},{"kind":"witness","sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"}],"format":"scienting-receipt/1","id":"npc15pn6675z5","level":"F3","nodes":[["bnyvykm","13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94"],["c20cna6","7252bb19f33a3be672d74a8aa8323750311b5c7d2b8f6cf21e07f17f2b27f3a1"],["ztww0g8","bda85639faacb77e504c891c035012602836171c009ecfd21584de4d6461ba93"]],"rev":0,"root":"5aeacf3cbd00a10320411c374b3b503583d1786f10c31fa04cc55117eba266ea","scope":"targeted:lode","signature":{"key":"ana","scheme":"ed25519","value":"IVRJwo1fygoctDfalPkrwvd5G5JARIqlV2FqzdPmL/BMvdVSKU9sRFJeLKHR+lXDVy3DY7GJgrjPh6VDdJAkCg=="}} +{"at":"2026-10-11T15:02:11Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"avbhhey","sha256":"942c23ea73a297e69c2ae8a82abe88d688de2532cb3f6d3543d1107c54f65b2e"},{"kind":"crop","node":"b5gd0h1","sha256":"a0b6f761fe95f8f29ef6dc37901fa85c7a62857b50b0163ca67b0aab048e4d17"},{"kind":"crop","node":"bnyvykm","sha256":"2c560caeaf914f3521fd0e3fca433922fcb9408c184c9b72bcfa869adf5ed409"},{"kind":"crop","node":"c20cna6","sha256":"bdbf7a4d9e86609675e3fc124c21ce808053a52d6bc0f35b15e1ba39027f13af"},{"kind":"crop","node":"d1mhw8b","sha256":"3104c57d9f8fb38302b057ead3bc44456da94f7c17d7c5c8f6db8732d4812c31"},{"kind":"crop","node":"ec5jc93","sha256":"321a926653b9e097987d255d9286880893d71abf895d73f1649403ed9ac0877d"},{"kind":"crop","node":"exms5gc","sha256":"cfc0e42e734470df5cfb741f92080526ef796bf48bcf05847d44f7091cfaaab1"},{"kind":"crop","node":"ganq1ns","sha256":"81d88697cd002fdfd770ee11413c550e4e4ffaa464d35841648311f278fc13bc"},{"kind":"crop","node":"hca6dc5","sha256":"a26619c3a9824bc19fddcf89ee618d9a4792d69110439f121eb717b6f98e88a6"},{"kind":"crop","node":"j6y45v6","sha256":"e689deda15dde9ad24433eb946200417473d273a1bf3136df67bf572256a483f"},{"kind":"crop","node":"jv1741a","sha256":"de60579bacfab769f614fa74d26d20c7b1aa02caf60af1479dc46b98ddcbc106"},{"kind":"crop","node":"k6a6616","sha256":"37b29d7ba293b27f913868690a785591d89ba9a4f47da8adaf764a4d5ae9675b"},{"kind":"crop","node":"m1p1n2g","sha256":"369c69758d2d09cc3d42b2424723c4fbc75f9ceb6817da81ce183be7d36f045f"},{"kind":"crop","node":"rr20tev","sha256":"f57e2cfe704d52c712b01e993e492b121ffe8c4d0174b11a0b0fa21fc5b9930b"},{"kind":"crop","node":"ryhrskg","sha256":"e6f816d93cfff8418dbb771ba03a09fb89a3b2438f97fabfc4ebef7f78af0dbf"},{"kind":"crop","node":"tkxsmts","sha256":"5d8e205660c2c59dcaff119b5671ac11650974b5287d7d7b239a9118e9171a85"},{"kind":"crop","node":"vd76637","sha256":"389742a44f1291e2dc7d7a69acd09410c92ed8a305718b2ab86b0b09b23253f4"},{"kind":"crop","node":"w0gr97q","sha256":"588a38407463e5674714899e6cf359810ccfed98fefdd2c1a90e8cb2ed0a9d64"},{"kind":"crop","node":"w264b74","sha256":"0babb0cef51933b8744f5b22d075069d51e431d3bdc08cb5e35d7822097b5953"},{"kind":"crop","node":"x3ns64d","sha256":"6bd7423a5933eb89572ded1d40d2f5baf6f6fa2f3c46791de8210f201a94b9d1"},{"kind":"crop","node":"ycwgbx1","sha256":"5ee72aca6b32e45f961f9cb2ff70408e71fc9ed7fccd28e91eb86e872041fed3"},{"kind":"crop","node":"yvkd7xr","sha256":"62fd5beecb3e76f430dfd142f443158b84657196af17173a976345a0cdd74449"},{"kind":"crop","node":"ztww0g8","sha256":"902e8ca35e1a313a81130c4c100aeb2233fd53854677b3a992fb16f744fe3151"},{"kind":"witness","sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"}],"format":"scienting-receipt/1","id":"y2zw8ctg5s8dp","level":"F3","nodes":[["avbhhey","c51730c0b1d7e11b51b317163ae42838f1be808b3690f196923482c9021f97c0"],["b5gd0h1","9635a750ac2acf526a4db28746fd3ed84659f4e384f5a73fef85d002b4e9308b"],["bnyvykm","13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94"],["c20cna6","c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272"],["d1mhw8b","557a47334329925d191e772172fddbc1bd1a035eb2217240c476ee6bc43c92ab"],["ec5jc93","5421e9cf0ef3a995792963d0371b79e11a8efad519b02efb5cb88311a896d0cc"],["exms5gc","b7c47f8360eb7272d2ac0943e8bf1aec9d71cb4ea4e5e1d02f8acee5b430a038"],["ganq1ns","40d46db2088057debc3b1d5b4a3c972ff3a94fc3d5463565f98876d0927f1e67"],["hca6dc5","8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34"],["j6y45v6","00c4b92e220303ebc2bfb36aa557ac80ae4dba1675e9ed47adb82f6aeff10634"],["jv1741a","f644190803b5ea36aa24738e7f168a7fdf0d05cb5123c14a814b7628dab71f1e"],["k6a6616","90aa63a43587bdcee8e428c7dc7a95ac1502bdbcb9f49cae05c433db6d18348b"],["m1p1n2g","0847b5d75c2259257c3619e761c64d5571d3ca3932e96a96ee07e8ce68cc63be"],["rr20tev","76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7"],["ryhrskg","525583990e7871a2ba55739e8206abac2df0f19d30c86ad74f6cafdd7c3cbe25"],["tkxsmts","cc0bf73dd84e298da0d36c4b363c8d2bdc9b6d5738d1923d14c4a9028dca08d6"],["vd76637","33810e4da42f8e65a224b5369c06fe8db254890294b7b6760808fe6e039da21a"],["w0gr97q","f738a008336ac59b2f1d45cda2f045dc96d34f0f1378c431ce6ff8e434feb8a7"],["w264b74","2ba9cea0f5c07ee9f7b47c5d541c85e92465709322869fb6c0d994ab61c56cad"],["x3ns64d","6bfc0a055148d877dbaf28b7f62565de7b6926137bf032c382282c39a4876797"],["ycwgbx1","167d1551ca64cad5b1143431c5af6d3fc24530887470b7fd265df88d1f54f267"],["yvkd7xr","aab8791a24bc4067c7e37fc5f0244d2128205e0a169e65c2c0fad977aabce313"],["ztww0g8","bda85639faacb77e504c891c035012602836171c009ecfd21584de4d6461ba93"]],"rev":12,"root":"373a7d860a14b58e5bfa9b9ad3bc916091bcb6db7556f0dbc9c71972a612494d","scope":"targeted:lode","signature":{"key":"ana","scheme":"ed25519","value":"2sraHCMlItocGta02EhvPlDW+F8rB1ZYMXBzA5lmNmtH0h+AlrNOPTbtykVSAWQXfKT2DXuB81/6x5jyNsIVBA=="}} +{"at":"2026-10-11T16:30:00Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"a4jrz2t","sha256":"46790e75ae8cff068515a73b05642be78939e4dd8bad40a080e0d135ba838799"},{"kind":"crop","node":"kea5026","sha256":"1ee24fc6dec45a1372134888b70ad35e4823bdfe7d3e57d2dab08e9d7d329356"},{"kind":"witness","sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"}],"format":"scienting-receipt/1","id":"mvjmb94nz7rdh","level":"F3","nodes":[["a4jrz2t","f64c6a5040f9c773d5ac4e559b58465aeae30bba79a82fc38b14ac7b61826ba8"],["kea5026","b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33"]],"rev":12,"root":"5e3134a4583e5ea26e575da2a363a0520a7ee111f4da782c641e8c24070f8895","scope":"section:p36k8t6","signature":{"key":"ana","scheme":"ed25519","value":"tprithiSRx7h9KjqJrVCq7zK3ZufvNmACZNFORVde8I0sQUZgq6RTx9orJP3okDZj1I9/gGwJ9Fv1cCVBCYEAw=="}} +{"at":"2026-10-11T17:00:00Z","by":"cara","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"qwgfg51","sha256":"886b5234b8240653d2a1f9551552592d3e64792658980b06b2d38f1af61b51d8"},{"kind":"crop","node":"vya7t4n","sha256":"4ef9dce7bed5821302a3fe118dbe32395df49cab231723cc1fe1d2b3b15093f1"},{"kind":"crop","node":"xjns57z","sha256":"57d07288058274f0e54c57899476eec6ddfc2662043ec609b5b91315bf0a4786"},{"kind":"witness","sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"}],"format":"scienting-receipt/1","id":"q465jpwz8afhe","level":"F3","nodes":[["qwgfg51","4a3be03766323b3c88d5b43591b0f573823b89fe582f2c3a6f0b43474685a30d"],["vya7t4n","5e7362eb5c7cd2db425e557982083a51c2607521b6b1f73d79d98956616965df"],["xjns57z","42b1de7852cdc68730984fff789fe248ecd5b43198c0e7d671931ff3fe561dc3"]],"rev":12,"root":"36aeaeab7720b10ffbbe12d07751ac3273c77fc642355e00e795cbe7db73b3b0","scope":"page:2","signature":{"key":"cara","scheme":"ed25519","value":"QY2hQLVWKyOLkSCQNzTOskn5suI4s1WmflgrQDvB43IyBx5AOP4qXdvyKdkvb1YJ+puHdpDi53/4Ad92jKYPCQ=="}} +{"at":"2026-10-11T17:20:00Z","by":"cara","format":"scienting-revocation/1","id":"pcbhtpwvysgq6","reason":"Signed against the crops of another paper.","receipt":"q465jpwz8afhe","signature":{"key":"cara","scheme":"ed25519","value":"hObSv+xgW3GLZPkkR08CB+9LdxPP+16j/C/eI4OnqeuvbamQwDv7uZJmHBNBG1GkU+TcVM0V4IbDNfpuYyO4DQ=="}} +{"at":"2026-10-11T18:00:00Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"caehhp6","sha256":"03932451473e6756936d196da5db53b9027220ab90402f32c212ed02a3e0cb69"},{"kind":"crop","node":"nms5qjg","sha256":"87a410886dac6569211ac21d5787953e6cb538b691d1cee916eb9ae72061ebba"},{"kind":"crop","node":"z86b2za","sha256":"3bd36b4ee0d38edfcd3e8feb546e24693cd8034e6ce3c11f01d2be8871f38c76"},{"kind":"witness","sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"}],"format":"scienting-receipt/1","id":"gx2s84z9jf9xv","level":"F3","nodes":[["caehhp6","9f9c9a412cd08d0634daa3f23c63f5125c1270c13834c45c045c1a9a7452af86"],["nms5qjg","e2f0b1d093c2f38f329c16edae255aed6e913d489e730a9d4857a3c3b5040f63"],["z86b2za","9a1c438b0f413d63b7e9f1ed7037cc6ad1665efd335baee2ef31d3d232c79552"]],"rev":12,"root":"1d4c44e1018708ff37d9e4b6b722b55388f627a2a9d00c32ea4dcbb0dad4a976","scope":"targeted:captions","signature":{"key":"ana","scheme":"ed25519","value":"nsms22ca/Cff9M6lamEOyn81qL/+OJg9uSDcXVny91XFQAlKZ3s3hS/Xf+8snrhCsuNEOqEfHYpg0nnVAFnwAQ=="}} +{"at":"2026-10-12T09:00:00Z","by":"ben","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"bnyvykm","sha256":"2c560caeaf914f3521fd0e3fca433922fcb9408c184c9b72bcfa869adf5ed409"},{"kind":"crop","node":"c20cna6","sha256":"bdbf7a4d9e86609675e3fc124c21ce808053a52d6bc0f35b15e1ba39027f13af"},{"kind":"crop","node":"d1mhw8b","sha256":"3104c57d9f8fb38302b057ead3bc44456da94f7c17d7c5c8f6db8732d4812c31"},{"kind":"crop","node":"exms5gc","sha256":"cfc0e42e734470df5cfb741f92080526ef796bf48bcf05847d44f7091cfaaab1"},{"kind":"crop","node":"ganq1ns","sha256":"81d88697cd002fdfd770ee11413c550e4e4ffaa464d35841648311f278fc13bc"},{"kind":"crop","node":"m1p1n2g","sha256":"369c69758d2d09cc3d42b2424723c4fbc75f9ceb6817da81ce183be7d36f045f"},{"kind":"crop","node":"ryhrskg","sha256":"e6f816d93cfff8418dbb771ba03a09fb89a3b2438f97fabfc4ebef7f78af0dbf"},{"kind":"crop","node":"w264b74","sha256":"0babb0cef51933b8744f5b22d075069d51e431d3bdc08cb5e35d7822097b5953"},{"kind":"crop","node":"yvkd7xr","sha256":"62fd5beecb3e76f430dfd142f443158b84657196af17173a976345a0cdd74449"},{"kind":"crop","node":"ztww0g8","sha256":"902e8ca35e1a313a81130c4c100aeb2233fd53854677b3a992fb16f744fe3151"}],"format":"scienting-receipt/1","id":"mg18668nzxvap","level":"F3","nodes":[["bnyvykm","13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94"],["c20cna6","c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272"],["d1mhw8b","557a47334329925d191e772172fddbc1bd1a035eb2217240c476ee6bc43c92ab"],["exms5gc","b7c47f8360eb7272d2ac0943e8bf1aec9d71cb4ea4e5e1d02f8acee5b430a038"],["ganq1ns","40d46db2088057debc3b1d5b4a3c972ff3a94fc3d5463565f98876d0927f1e67"],["m1p1n2g","0847b5d75c2259257c3619e761c64d5571d3ca3932e96a96ee07e8ce68cc63be"],["ryhrskg","525583990e7871a2ba55739e8206abac2df0f19d30c86ad74f6cafdd7c3cbe25"],["w264b74","2ba9cea0f5c07ee9f7b47c5d541c85e92465709322869fb6c0d994ab61c56cad"],["yvkd7xr","aab8791a24bc4067c7e37fc5f0244d2128205e0a169e65c2c0fad977aabce313"],["ztww0g8","bda85639faacb77e504c891c035012602836171c009ecfd21584de4d6461ba93"]],"qa":{"errors":[],"key":"ben-spot","minimum":10,"of":"y2zw8ctg5s8dp","rate":"0.05","sample":["bnyvykm","c20cna6","d1mhw8b","exms5gc","ganq1ns","m1p1n2g","ryhrskg","w264b74","yvkd7xr","ztww0g8"],"seed":"3vORmZaL4zpWgtbZM29fKrWxgKOHhtXspIkutCyqgZgWUaBvmYCQfHtmCID+YNW2M+LIr8uMlpq/LD5cIp0omQRDdKSTIdrxoCxQHFgcwg0="},"rev":12,"root":"1819b7c2f0e597c440ac79096630f9e2e3cf915bedde34a0dbacae09e4ffee13","scope":"qa:y2zw8ctg5s8dp","signature":{"key":"ben","scheme":"ed25519","value":"iQZEJAY4djubmhFAFBq/wu4N0zoZly8ahIuVwQtra10NCxqSce2v+NCxu8dj+5xTWuOObdUHFVnbAVDdRBFJDQ=="}} +{"at":"2026-10-12T09:30:00Z","by":"ben","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"caehhp6","sha256":"03932451473e6756936d196da5db53b9027220ab90402f32c212ed02a3e0cb69"},{"kind":"crop","node":"nms5qjg","sha256":"87a410886dac6569211ac21d5787953e6cb538b691d1cee916eb9ae72061ebba"},{"kind":"crop","node":"z86b2za","sha256":"3bd36b4ee0d38edfcd3e8feb546e24693cd8034e6ce3c11f01d2be8871f38c76"}],"format":"scienting-receipt/1","id":"yt70fcc3qm0xb","level":"F3","nodes":[["caehhp6","9f9c9a412cd08d0634daa3f23c63f5125c1270c13834c45c045c1a9a7452af86"],["nms5qjg","e2f0b1d093c2f38f329c16edae255aed6e913d489e730a9d4857a3c3b5040f63"],["z86b2za","9a1c438b0f413d63b7e9f1ed7037cc6ad1665efd335baee2ef31d3d232c79552"]],"qa":{"errors":[{"kind":"word","node":"caehhp6","note":"The page prints a period the reading lacks."}],"key":"ben-spot","minimum":10,"of":"gx2s84z9jf9xv","rate":"0.05","sample":["caehhp6","nms5qjg","z86b2za"],"seed":"OGWvNMD0Wsd3kUTzvby0kVC6P1h4UKOMD+vVidd489IfuQIsp68CVEYuGwovPKNdHuIvBCYZL+2WoHbY5ClR8yH0r4t4JXV+2JGsGPbb+gs="},"rev":12,"root":"1d4c44e1018708ff37d9e4b6b722b55388f627a2a9d00c32ea4dcbb0dad4a976","scope":"qa:gx2s84z9jf9xv","signature":{"key":"ben","scheme":"ed25519","value":"9j18am+VrPqloaPVfPZoh0nbyGB4d1rWDwQdsb+NjD3+TMjNQbcVv0CRtgwWCLTw9ibMtk4XNRqDN7ImqpV0CA=="}} diff --git a/fixtures/packages/hale2026harmonic-damb/references.jsonl b/fixtures/packages/hale2026harmonic-damb/references.jsonl new file mode 100644 index 0000000..ba64f14 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/references.jsonl @@ -0,0 +1,2 @@ +{"csl":{"DOI":"10.5555/example.ref1","author":[{"family":"Author","given":"A."},{"family":"Author","given":"B."}],"container-title":"J. Example Chem.","issued":{"date-parts":[[2001]]},"page":"345-350","type":"article-journal","volume":"12"},"label":"1","node":"tb6syqq","resolution":{"doi":"10.5555/example.ref1","type":"doi"}} +{"csl":{"author":[{"family":"Writer","given":"C."}],"container-title":"Example Spectroscopy","issued":{"date-parts":[[2010]]},"page":"89-97","type":"article-journal","volume":"7"},"label":"2","node":"vxsdvzq","resolution":{"type":"none"}} diff --git a/fixtures/packages/hale2026harmonic-damb/roster.json b/fixtures/packages/hale2026harmonic-damb/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/packages/hale2026harmonic-damb/witnesses.json b/fixtures/packages/hale2026harmonic-damb/witnesses.json new file mode 100644 index 0000000..737fc22 --- /dev/null +++ b/fixtures/packages/hale2026harmonic-damb/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"qptsanv","kind":"pdf","media_type":"application/pdf","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"pages":2,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834","size":482113,"text_layer":true,"version_label":"version of record"}]} diff --git a/fixtures/packages/okafor2025solvent-acth/MANIFEST.json b/fixtures/packages/okafor2025solvent-acth/MANIFEST.json new file mode 100644 index 0000000..0c1035a --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"a26e65325ed01720c255480854d270d740d011aa29e39c667a80917fd78243ea","size":1050},{"path":"locations.jsonl","sha256":"d677b09e9adc6480c78e921cd0b09ef2aab618f36e5834a162be65bc57ea53f3","size":1161},{"path":"nodes.jsonl","sha256":"09c9b99eed97987e51dd0f85461ad9ad8768a0769ba7facfb7e0879d742660a3","size":8669},{"path":"pages.jsonl","sha256":"d356f4a78bd2427e750943648c9d37977ac0144ff85bedc013b60d934b1501cf","size":170},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"references.jsonl","sha256":"f307b3e3dddfa0199a5a4c1af64382320c0921febe904948abd86a96febe18f1","size":332},{"path":"witnesses.json","sha256":"7bb40440b8b04d5193600f04ba6452cb4062046652f0f924d60d6b0c5aa86876","size":1901}],"format":"scienting-package/1","key":"okafor2025solvent-acth"} diff --git a/fixtures/packages/okafor2025solvent-acth/document.json b/fixtures/packages/okafor2025solvent-acth/document.json new file mode 100644 index 0000000..feb3453 --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":7,"nodes":15},"fidelity":{"counts":{"F0":0,"F1":0,"F2":7,"F3":0},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"okafor2025solvent-acth","kind":"article","language":"en","license":{"spdx":"CC-BY-4.0","url":"https://creativecommons.org/licenses/by/4.0/"},"meta":{"DOI":"10.5555/example.okafor.2025","author":[{"family":"Okafor","given":"N."},{"family":"Lindqvist","given":"E."}],"container-title":"Open Example Letters","issued":{"date-parts":[[2025,11,20]]},"page":"e17","title":"Solvent shifts of a model carbonyl stretch","type":"article-journal","volume":"3"},"meta_hash":"af9342a56b8e7141d22ad34bbe076a90b9e278ff14d141d954941eada11c0555","policy":"full","relations":[],"rev":0,"root":"3a9f6936f251395f2d662c46786362f9fda52ccfc1813128a8acf4e7e9d78543","version":{"date":"2025-11-20","type":"version-of-record"},"work":{"key":"okafor2025solvent-acth","same_as":["doi:10.5555/example.okafor.2025"]}} diff --git a/fixtures/packages/okafor2025solvent-acth/locations.jsonl b/fixtures/packages/okafor2025solvent-acth/locations.jsonl new file mode 100644 index 0000000..bd93f9f --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/locations.jsonl @@ -0,0 +1,7 @@ +{"boxes":[[72,72,317.7,83.8]],"node":"h5ej3qh","page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1"} +{"boxes":[[72,85.95,224.1,97.75]],"node":"bka8a6q","page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1"} +{"boxes":[[72,99.9,112.95,111.7]],"node":"vbwtwn6","page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1"} +{"boxes":[[72,113.85,540,125.65],[72,127.8,159.75,139.6]],"node":"n2cw4vp","page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1"} +{"boxes":[[72,141.75,540,153.55],[72,155.7,241.65,167.5]],"node":"a2vwxk9","page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1"} +{"boxes":[[72,169.65,522.45,181.45]],"node":"m298qtj","page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1"} +{"boxes":[[72,183.6,463.95,195.4]],"node":"advcsz6","page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1"} diff --git a/fixtures/packages/okafor2025solvent-acth/nodes.jsonl b/fixtures/packages/okafor2025solvent-acth/nodes.jsonl new file mode 100644 index 0000000..0e5b0c3 --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/nodes.jsonl @@ -0,0 +1,15 @@ +{"align_key":"8cd5cb4da02aeefdd10abbb18250ef83a237cb7f16db3cf9d29e68e80e7e4ea7","id":"hpct6zz","kind":"document","match_hash":"657745125e6254f97d45f126d142e3b02a5cc3a2f3724eb26853d958f5058bc7","node_hash":"3a9f6936f251395f2d662c46786362f9fda52ccfc1813128a8acf4e7e9d78543","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"50ccfbc9b01871b08bab598d19339143954f4269c8bc74569b6cdd1c925f706f"} +{"align_key":"1f61427c5da3340c67fd917d0058b4524fdb933d9908c1e94498be77d5554a0a","id":"mheb7ff","kind":"front","match_hash":"5e9f2da54785485697d24dc14b137622e848c1db262aa22e0d391dbafd422f71","node_hash":"efedca8a0e93a7d83fe84a3f66e2e8895e531d2091eb2bc00c36b4f5424d4945","ord":0,"own_hash":"0167516d70e0a89263e33c0f9be5ca4443113347814530257a60d43910af71b6","parent":"hpct6zz","text_hash":"5e9f2da54785485697d24dc14b137622e848c1db262aa22e0d391dbafd422f71"} +{"align_key":"2326122dd72e54bbe6f47e4fb961706b6d0d0cd33f9514619eb12031c7b31451","id":"kq3b02h","kind":"title","match_hash":"1a652d752f6450bff4171a9477781fceb2e7a8329d3407a8db2ed95fcc75eea7","node_hash":"548af4b902dce58ed70f7ba0b77469f0129c52d8609c81fe822620e5d031c0be","ord":0,"own_hash":"c22e4fc822618a3a2c774cc9ea6fc5fc5b34463724257cfa4fd33022d4e35165","parent":"mheb7ff","text_hash":"1a652d752f6450bff4171a9477781fceb2e7a8329d3407a8db2ed95fcc75eea7"} +{"align_key":"2326122dd72e54bbe6f47e4fb961706b6d0d0cd33f9514619eb12031c7b31451","content":[{"kind":"text","text":"Solvent shifts of a model carbonyl stretch"}],"fidelity":"F2","id":"h5ej3qh","kind":"sentence","match_hash":"1a652d752f6450bff4171a9477781fceb2e7a8329d3407a8db2ed95fcc75eea7","node_hash":"526621b446f65afcd56e8986745b6ffc9425831f39cc7889a8e04416b943848f","ord":0,"own_hash":"bbb9b0384479c456c6ed1fae926b731e302f09fa5017deddd0dd463dd7d11685","parent":"kq3b02h","prov":{"backend":"jats reader (illustrative)","corroborated_by":["ve93xh4"],"witnesses":["wgsxda1","ve93xh4"]},"text_hash":"1a652d752f6450bff4171a9477781fceb2e7a8329d3407a8db2ed95fcc75eea7"} +{"align_key":"c23ec91a29b63dfd088d0836b8849e2d584353575cb3b437297a77f49409150c","content":[{"kind":"text","text":"N. Okafor and E. Lindqvist"}],"fidelity":"F2","id":"bka8a6q","kind":"authors","match_hash":"11c23752a905b072cb2e593e841f40dc9960a667b6e2e6c2b1664bba62e94017","node_hash":"58e0477403095db24b1e0abcda04e36ddec635a8af776ed3f994c6900f28ddef","ord":1,"own_hash":"8290fe97e6d51800e6291cc181be1a27029c6baf672e063af44bcf4a06cef230","parent":"mheb7ff","prov":{"backend":"jats reader (illustrative)","corroborated_by":["ve93xh4"],"witnesses":["wgsxda1","ve93xh4"]},"text_hash":"11c23752a905b072cb2e593e841f40dc9960a667b6e2e6c2b1664bba62e94017"} +{"align_key":"9cb1ae8215cb626331b6848effd36fcbbfb5fa23d34edf3e8c544ff697a822af","attrs":{"level":1},"id":"rpb2dax","kind":"section","label":"1","match_hash":"d06ee8487e6453f4f68c92209c004917843c1d35b23749ae798a57d3b1e44c3a","node_hash":"e56e87f14032d93830176da63e41388b9ddfc1b6895e766b5763bc2209dbcfcd","ord":1,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"hpct6zz","text_hash":"83d46654d1c0ccab24ea7cf3e3de686cbf0e6f4f4fc269d0dc24e49a5a225c2e"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"xhv4hx1","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"rpb2dax","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"vbwtwn6","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"xhv4hx1","prov":{"backend":"jats reader (illustrative)","corroborated_by":["ve93xh4"],"witnesses":["wgsxda1","ve93xh4"]},"text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"403a19fa57756a120ee49a89500796a4de013c2f5d9330cc7f9b23a4bb0f4cab","id":"bzs2sc1","kind":"paragraph","match_hash":"8e4c2d662fbfa2bacce17400a3f377fc0b680c67ca551e81599dbfa0877e7df6","node_hash":"185bea488cbccd9c06cc0fe75e389e33b53e1a602085f4a6b87df1f2e1808d1b","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"rpb2dax","text_hash":"d980dce1880ef9991f67ff907772c3965848b89c239d2582ff722d0b77b44515"} +{"align_key":"320bf26bc5bfdc64ae68579ca9db4bbe63894954a8f9bd8110516ba724e955e6","content":[{"kind":"text","text":"The carbonyl band of the model ketone moves from 1718 cm⁻¹ in hexane to 1702 cm⁻¹ in methanol."},{"kind":"cite","refs":["advcsz6"],"text":"1"}],"fidelity":"F2","id":"n2cw4vp","kind":"sentence","match_hash":"14a204207b562594926a49f9ccc9edb565ebf95119050960cf3516d3939e5c02","node_hash":"a96921137ee751c77bb69c1bbc2f1e7b5559703db1898cc8029d1b8406da1468","ord":0,"own_hash":"b9fad53155671e316891b60f9e3ee2b9119b5a4fa6a11e4da90dddf7a87c2e68","parent":"bzs2sc1","prov":{"backend":"jats reader (illustrative)","corroborated_by":["ve93xh4"],"witnesses":["wgsxda1","ve93xh4"]},"text_hash":"caf74b1fc67f6225012f3b073e4351dbbee756e1548524876821da03726585e9"} +{"align_key":"ee6b1f09db1c2c1ecdd472a7b977c599c9358a99cdb5686ac567b87f10563058","content":[{"kind":"text","text":"The shift scales with the solvent's hydrogen-bond donor strength, "},{"kind":"math","notation":"tex","source":"\\alpha"},{"kind":"text","text":", with a slope of "},{"kind":"math","notation":"tex","source":"-17 \\pm 2"},{"kind":"text","text":" cm⁻¹."}],"fidelity":"F2","id":"a2vwxk9","kind":"sentence","match_hash":"b91a25c2a26df0fd2b0f6e078d51205f0bf1ed800d9e186596a1f17635560c61","node_hash":"4552064aad475c91e09fac26401c018ce415a3438e8e36b73e553fa6c0b824b4","ord":1,"own_hash":"09dab11852510630aea3d60647504643982d9fe74d7971fddc6db8fd7186e711","parent":"bzs2sc1","prov":{"backend":"jats reader (illustrative)","corroborated_by":["ve93xh4"],"witnesses":["wgsxda1","ve93xh4"]},"text_hash":"61e70f23d27be7bf6f6a55261aeef9876f186161790f2d77e01ce8a801bb82b7"} +{"align_key":"48406493bc8dce5299b7421aa8721c79472095541115bd81dacc2336c9ede87e","content":[{"kind":"text","text":"Two outliers, both fluorinated alcohols, fall below the line by about 4 cm⁻¹."}],"fidelity":"F2","id":"m298qtj","kind":"sentence","match_hash":"628ecf0b3c3c5174f288fbcc2ff8e77d785b917f8883d4b060b8c752d6f08e1b","node_hash":"13196be2e988bbc5d112a7707c2e9a03a17a52b7b0cac1ca370496460521f59f","ord":2,"own_hash":"01df573737002d488a329f9e93ef7a1c78f5732e9cfdf56d422c396d6c361858","parent":"bzs2sc1","prov":{"backend":"jats reader (illustrative)","corroborated_by":["ve93xh4"],"witnesses":["wgsxda1","ve93xh4"]},"text_hash":"87c9e583aa8ae555364746a3bc2692eb6deba81b0d555dff4063beb6ffa7069c"} +{"align_key":"cfd764699b7f3258e195e70e4d43863f8f3e82155ccc4228958083b30d9bd714","id":"ywttcpz","kind":"back","match_hash":"27595c7766cb1d3efcda047460eea43b2e5769f7fe8d9dfdba9953f60306f294","node_hash":"0b043ed2a532d458c5e18467fb9deb73e2b6becd7b98afb78aafc050fc9419b2","ord":2,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"hpct6zz","text_hash":"9642d5171c6ae6c4137f0d039798b75c0ddeb397216f23f0b64abb706ae0240d"} +{"align_key":"cfd764699b7f3258e195e70e4d43863f8f3e82155ccc4228958083b30d9bd714","id":"nzae82m","kind":"references","match_hash":"27595c7766cb1d3efcda047460eea43b2e5769f7fe8d9dfdba9953f60306f294","node_hash":"c49cf7f4016112276ca30802dd302729b2042a1bb8b1ef2106cf6d3ff02cbd91","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"ywttcpz","text_hash":"9642d5171c6ae6c4137f0d039798b75c0ddeb397216f23f0b64abb706ae0240d"} +{"align_key":"cfd764699b7f3258e195e70e4d43863f8f3e82155ccc4228958083b30d9bd714","content":[{"kind":"text","text":"1. P. Example and Q. Example, Spectrochim. Example 2019, 30, 11–19."}],"fidelity":"F2","id":"advcsz6","kind":"reference","label":"1","match_hash":"27595c7766cb1d3efcda047460eea43b2e5769f7fe8d9dfdba9953f60306f294","node_hash":"a17b597cf7e8bbb3dfa7e56953c78be82eb5074b4864bfd7098d2b75339d1a0a","ord":0,"own_hash":"2e577487892c6e75c10a22a75409f7ddba18b578d48c3994f751048d75a3941d","parent":"nzae82m","prov":{"backend":"jats reader (illustrative)","corroborated_by":["ve93xh4"],"witnesses":["wgsxda1","ve93xh4"]},"text_hash":"9642d5171c6ae6c4137f0d039798b75c0ddeb397216f23f0b64abb706ae0240d"} diff --git a/fixtures/packages/okafor2025solvent-acth/pages.jsonl b/fixtures/packages/okafor2025solvent-acth/pages.jsonl new file mode 100644 index 0000000..a629ffd --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/pages.jsonl @@ -0,0 +1 @@ +{"page":1,"page_fp":"2a37af2c78e19e5ade6c7c2f72b6095a50bea910448fc0ef932dec5663b777ff","page_label":"e17-1","size":[595.28,841.89],"text_layer":true,"witness":"ve93xh4"} diff --git a/fixtures/packages/okafor2025solvent-acth/provenance.json b/fixtures/packages/okafor2025solvent-acth/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/packages/okafor2025solvent-acth/references.jsonl b/fixtures/packages/okafor2025solvent-acth/references.jsonl new file mode 100644 index 0000000..242f333 --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/references.jsonl @@ -0,0 +1 @@ +{"csl":{"DOI":"10.5555/example.ref3","author":[{"family":"Example","given":"P."},{"family":"Example","given":"Q."}],"container-title":"Spectrochim. Example","issued":{"date-parts":[[2019]]},"page":"11-19","type":"article-journal","volume":"30"},"label":"1","node":"advcsz6","resolution":{"doi":"10.5555/example.ref3","type":"doi"}} diff --git a/fixtures/packages/okafor2025solvent-acth/witnesses.json b/fixtures/packages/okafor2025solvent-acth/witnesses.json new file mode 100644 index 0000000..ade496b --- /dev/null +++ b/fixtures/packages/okafor2025solvent-acth/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"wgsxda1","kind":"jats","media_type":"application/xml","origin":{"doi":"10.5555/example.okafor.2025","source":"repository"},"rights":{"asserted_by":{"by":"crossref","evidence":[{"doi":"10.5555/example.okafor.2025","kind":"crossref-license","url":"https://creativecommons.org/licenses/by/4.0/"}]},"at":"2026-09-15T12:00:00Z","basis":"open-license","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0","url":"https://creativecommons.org/licenses/by/4.0/"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"54867ad507a8ba202b027c3e591761dabc57f9486c2e53c37528a8b11614af2e","size":38211,"version_label":"version of record"},{"id":"ve93xh4","kind":"pdf","media_type":"application/pdf","origin":{"doi":"10.5555/example.okafor.2025","source":"publisher"},"pages":1,"rights":{"asserted_by":{"by":"crossref","evidence":[{"doi":"10.5555/example.okafor.2025","kind":"crossref-license","url":"https://creativecommons.org/licenses/by/4.0/"}]},"at":"2026-09-15T12:00:00Z","basis":"open-license","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0","url":"https://creativecommons.org/licenses/by/4.0/"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"7f7247d890babeb09940267a977cb84b9c81fdc5905bab0515d20fe2fbf2498c","size":201977,"text_layer":true,"version_label":"version of record"}]} diff --git a/fixtures/packages/tiny2026tiny-j4qm.sct.zip b/fixtures/packages/tiny2026tiny-j4qm.sct.zip new file mode 100644 index 0000000..10a4fe9 Binary files /dev/null and b/fixtures/packages/tiny2026tiny-j4qm.sct.zip differ diff --git a/fixtures/packages/tiny2026tiny-j4qm/MANIFEST.json b/fixtures/packages/tiny2026tiny-j4qm/MANIFEST.json new file mode 100644 index 0000000..6be6656 --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"e10c4aaab285d02d859ed2cf590fa9add9b77b0fab7a2b71b8c82f61b310a031","size":764},{"path":"nodes.jsonl","sha256":"6ce54e0d837dceb4a2a39c1b2618cc66e16684b93f71b93ab4e6e709a90b0e52","size":11295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"receipts.jsonl","sha256":"f745067d43480bbd467c5d8f11ff13eec198fac821664894ad8bd90b8b7cf0b3","size":2182},{"path":"references.jsonl","sha256":"59908a8aff6a2d5800747a1f45c6c2943ea1e31e7e1f10b6348967d30f16b87e","size":60},{"path":"roster.json","sha256":"3c71b0c007924cbacd3b4af02485214ab904db8ff8fca133ab32e67c5c76d481","size":6941},{"path":"witnesses.json","sha256":"83ac4411c2efe65e0f7fc4c9336abbef6977cd32b0f90de029a7f8516afc3e97","size":750}],"format":"scienting-package/1","key":"tiny2026tiny-j4qm"} diff --git a/fixtures/packages/tiny2026tiny-j4qm/document.json b/fixtures/packages/tiny2026tiny-j4qm/document.json new file mode 100644 index 0000000..9a4e921 --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":10,"nodes":22},"fidelity":{"counts":{"F0":0,"F1":0,"F2":1,"F3":9},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"tiny2026tiny-j4qm","kind":"article","language":"en","license":{"spdx":"CC0-1.0"},"meta":{"author":[{"family":"Tiny","given":"T."}],"issued":{"date-parts":[[2026]]},"title":"A tiny example"},"meta_hash":"1062e6079e2871c390f4737f5354448b65fe524d8c09d1c82afaa8b71ba6b3e7","policy":"full","relations":[],"rev":0,"root":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","version":{"type":"version-of-record"},"work":{"key":"tiny2026tiny-j4qm","same_as":["doi:10.5555/example.tiny.2026"]}} diff --git a/fixtures/packages/tiny2026tiny-j4qm/nodes.jsonl b/fixtures/packages/tiny2026tiny-j4qm/nodes.jsonl new file mode 100644 index 0000000..f08057c --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/nodes.jsonl @@ -0,0 +1,22 @@ +{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"} +{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"} +{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"} +{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"} +{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"} +{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"} +{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"} +{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"} +{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"} +{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"} +{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"} +{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"} +{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} +{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"} diff --git a/fixtures/packages/tiny2026tiny-j4qm/provenance.json b/fixtures/packages/tiny2026tiny-j4qm/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/packages/tiny2026tiny-j4qm/receipts.jsonl b/fixtures/packages/tiny2026tiny-j4qm/receipts.jsonl new file mode 100644 index 0000000..d0952d1 --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/receipts.jsonl @@ -0,0 +1 @@ +{"at":"2026-10-11T12:00:00Z","by":"ana","doc":"tiny2026tiny-j4qm","evidence":[{"kind":"crop","node":"af5b51r","sha256":"78b08276b5122feed3829e8dd19684fa8a4a41f79cb83a499d40341e09f5d658"},{"kind":"crop","node":"ajqxkgh","sha256":"398bab4177685c88eef399d814d34c81baa556d58cd508bd5ddb33ac53a5cbfa"},{"kind":"crop","node":"f463wj7","sha256":"88b1e820b569c3a0fd025a6b6c502271ed73bbce720dd8a2e416d6a5dd0e9d67"},{"kind":"crop","node":"j663d4h","sha256":"d6484c89588a560f64bbceca108f5446e47bb5cb85521fbffc9d6d37f252e5c7"},{"kind":"crop","node":"jvnys4s","sha256":"3139fb30b88062bd0c6bbb028c4c57fc748218ce1d7a612d282e292d6a02ffe9"},{"kind":"crop","node":"mzwwhxj","sha256":"83a7fcf09321f8a644c58120f80dede5d73d89f50d080ccbb143ec5b485e3088"},{"kind":"crop","node":"r3e21zr","sha256":"ff809e11101fa6ff5422e5232e83142c1a43dada0e56d63ec03fbce3474dd1aa"},{"kind":"crop","node":"rdrqkv7","sha256":"c0699aceb344812ebebb1414838641f0761184d5113dcc870d07c721fd289437"},{"kind":"crop","node":"rsw24qc","sha256":"b4c3b133c707b1a9a2cec2efe5c17731bada0d6bace5b1fb3590c5c5ab18bb92"},{"kind":"witness","sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21"}],"format":"scienting-receipt/1","id":"k4wt522d9zvjr","level":"F3","nodes":[["af5b51r","59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5"],["ajqxkgh","838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87"],["f463wj7","f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd"],["j663d4h","443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab"],["jvnys4s","f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc"],["mzwwhxj","8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e"],["r3e21zr","71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed"],["rdrqkv7","87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df"],["rsw24qc","caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57"]],"rev":0,"root":"15d9c8bd5472afd7064578e5663d3b7fd21249adc6cdb40fcbe1b790e3fae801","scope":"all","signature":{"key":"ana","scheme":"ed25519","value":"/xOfCboOpgu29ztKi22IU9crgC5LYetrHOMpQtqj4QV5dVP73n/ze94hyPknYO5qNPgBmYRrbJZBIIHdwqxoAA=="}} diff --git a/fixtures/packages/tiny2026tiny-j4qm/references.jsonl b/fixtures/packages/tiny2026tiny-j4qm/references.jsonl new file mode 100644 index 0000000..af52739 --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/references.jsonl @@ -0,0 +1 @@ +{"label":"1","node":"r3e21zr","resolution":{"type":"none"}} diff --git a/fixtures/packages/tiny2026tiny-j4qm/roster.json b/fixtures/packages/tiny2026tiny-j4qm/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"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","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/packages/tiny2026tiny-j4qm/witnesses.json b/fixtures/packages/tiny2026tiny-j4qm/witnesses.json new file mode 100644 index 0000000..a7b09bb --- /dev/null +++ b/fixtures/packages/tiny2026tiny-j4qm/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"nmfryke","kind":"pdf","media_type":"application/pdf","origin":{"source":"author"},"pages":1,"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"fda3f1e9bb3538cd85dcc42281e00fd045f726652664439ce5a15d8489425b21","size":1000}]} diff --git a/fixtures/packages/writer2027fixed-ynr7.v3/MANIFEST.json b/fixtures/packages/writer2027fixed-ynr7.v3/MANIFEST.json new file mode 100644 index 0000000..7d03879 --- /dev/null +++ b/fixtures/packages/writer2027fixed-ynr7.v3/MANIFEST.json @@ -0,0 +1 @@ +{"doc":"scienting-doc/1","files":[{"path":"document.json","sha256":"882e41e87ffbaa617e55b13fe5f9c1bdfd2e6c53159a57ab17c0b6a8b12e8b7e","size":802},{"path":"nodes.jsonl","sha256":"3845502f83168047e51719c45fd8732b3e6b37741fb8944771cb9d18bc791518","size":8295},{"path":"provenance.json","sha256":"4bc7649bf6d3113f6c72b4016713654f57c8f03069632eabd1e6025c05cb9dac","size":226},{"path":"references.jsonl","sha256":"a854aa7fa3f337bd2641fe1986882b3d43acf2e83a65671cd4cfae6465103933","size":344},{"path":"witnesses.json","sha256":"badd17f82e6cc4aa8d116d2056d10b868fbf6978fa47947d89404c458b6a532c","size":766}],"format":"scienting-package/1","key":"writer2027fixed-ynr7.v3"} diff --git a/fixtures/packages/writer2027fixed-ynr7.v3/document.json b/fixtures/packages/writer2027fixed-ynr7.v3/document.json new file mode 100644 index 0000000..dd31228 --- /dev/null +++ b/fixtures/packages/writer2027fixed-ynr7.v3/document.json @@ -0,0 +1 @@ +{"counts":{"leaves":7,"nodes":15},"fidelity":{"counts":{"F0":0,"F1":0,"F2":7,"F3":0},"lowest":"F2"},"format":"scienting-doc/1","hashing":{"algorithm":"sha-256","scheme":"plain"},"history":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","key":"writer2027fixed-ynr7.v3","kind":"draft","language":"en","license":{"spdx":"CC-BY-4.0"},"meta":{"author":[{"family":"Writer","given":"A."}],"issued":{"date-parts":[[2027]]},"title":"Fixed charges in biomolecular force fields","type":"report"},"meta_hash":"6a844957c7f8e582c6f30d836e702f6fa816a1bea5d5c0e157b2cfbbacba0ec3","policy":"full","relations":[],"rev":0,"root":"5e9137c41b5832b63c299ce20732fe7afc91bc8de1c67496ff09f0272880c011","store":"smithlab","version":{"seq":3,"type":"draft"},"work":{"key":"writer2027fixed-ynr7","same_as":[]}} diff --git a/fixtures/packages/writer2027fixed-ynr7.v3/nodes.jsonl b/fixtures/packages/writer2027fixed-ynr7.v3/nodes.jsonl new file mode 100644 index 0000000..d4d7d84 --- /dev/null +++ b/fixtures/packages/writer2027fixed-ynr7.v3/nodes.jsonl @@ -0,0 +1,15 @@ +{"align_key":"1a2bb9eac1e4dc9f227cf4559731b2057dc2a9a2b9d6b54889a56d91cd87a782","id":"eaaw8zs","kind":"document","match_hash":"20454adf8e339b779917cfcb20d652557204568101ce947616928ef833350e2b","node_hash":"5e9137c41b5832b63c299ce20732fe7afc91bc8de1c67496ff09f0272880c011","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"beece988a027b059e0ff0a0097337b6fe347e680acdfe8e72e43452554fac195"} +{"align_key":"37108c46d3691a0fcb4a378eda3fe2cd7ab3843f22cfcc34d486d069123ea9a7","id":"nedkmhw","kind":"front","match_hash":"3d4535506043f6f04de395aeb16ea50f7f26f2ab341023fe1883f97c2749d406","node_hash":"e06b854f1015214643f375533f258b90470f06a08ac60a13b66b12dc7736bb39","ord":0,"own_hash":"0167516d70e0a89263e33c0f9be5ca4443113347814530257a60d43910af71b6","parent":"eaaw8zs","text_hash":"3d4535506043f6f04de395aeb16ea50f7f26f2ab341023fe1883f97c2749d406"} +{"align_key":"1c346b0b6df77616e3db9eebcff5d56ccc123715374eb60a0df1a6cbe1e059ec","id":"w7dabwn","kind":"title","match_hash":"d3c3de666d0290878de3949bc0e0ffcaef965c66d2b61e81a5e615e26a2997df","node_hash":"25cb59151aa6bb80d785263e14ffb762938f1a0991ff3a069a1fc6dc6fd42fc8","ord":0,"own_hash":"c22e4fc822618a3a2c774cc9ea6fc5fc5b34463724257cfa4fd33022d4e35165","parent":"nedkmhw","text_hash":"d3c3de666d0290878de3949bc0e0ffcaef965c66d2b61e81a5e615e26a2997df"} +{"align_key":"1c346b0b6df77616e3db9eebcff5d56ccc123715374eb60a0df1a6cbe1e059ec","content":[{"kind":"text","text":"Fixed charges in biomolecular force fields"}],"fidelity":"F2","id":"csgs20p","kind":"sentence","match_hash":"d3c3de666d0290878de3949bc0e0ffcaef965c66d2b61e81a5e615e26a2997df","node_hash":"a859025788a7d67363ba278fd6d67e4349ccb9bccb4c215f60271b3b70b0d549","ord":0,"own_hash":"102b7f337262638415717e077a41d3a4ae579b32a37c837c4ab404a075bf347f","parent":"w7dabwn","prov":{"backend":"typst reader (illustrative)","witnesses":["tszzg52"]},"text_hash":"d3c3de666d0290878de3949bc0e0ffcaef965c66d2b61e81a5e615e26a2997df"} +{"align_key":"6bb0f8a42947682adacb47add8ac5d59c3d49f02ee275e8d390acab500b441e1","content":[{"kind":"text","text":"A. Writer"}],"fidelity":"F2","id":"t5xv7jz","kind":"authors","match_hash":"cb38b0c8294dc57d6923a5aab72e1093289f2efbb69293d1f6f5702536a54720","node_hash":"282f0d59e22716e1c28ed5de02bf0729c309bec17bb2ab59c7cb2937c2dad1c0","ord":1,"own_hash":"f1fc7a0ac9b744d5f99583296e8a980e52f80a2a398f240803d457d68a124973","parent":"nedkmhw","prov":{"backend":"typst reader (illustrative)","witnesses":["tszzg52"]},"text_hash":"cb38b0c8294dc57d6923a5aab72e1093289f2efbb69293d1f6f5702536a54720"} +{"align_key":"2ae14f38f7c9c72752502a2766e9ac856f477479fe1456b47d2ef880f17e8eb4","attrs":{"level":1},"id":"tqcsy8w","kind":"section","label":"1","match_hash":"34e0c5261e9055e0fa15b1e1c95e2c6cf8f55f6a9fa0177f6dd36f09410864ea","node_hash":"818f509bcf5783450604a80a5bd200232a3ce88e446c8eca5feeb7e6d15f9c6a","ord":1,"own_hash":"78563e96f51db1954d3fabe08f3748956b564c87ba4c8f7954bf747545a37fcd","parent":"eaaw8zs","text_hash":"86a59f6424a18898cc62dc1413ad12a0cc2c8dfbd84d218c43316bc8659fddf2"} +{"align_key":"d3db5338aae140c5cc04ac37690aa4f98041e14a042bc6473d54ecda8d95f93e","id":"wxsngqp","kind":"heading","match_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e","node_hash":"c7288f33d2cb2ac9b9c146dabd403d2e64e793418bd31ac14802349543ac84c8","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"tqcsy8w","text_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e"} +{"align_key":"d3db5338aae140c5cc04ac37690aa4f98041e14a042bc6473d54ecda8d95f93e","content":[{"kind":"text","text":"Introduction"}],"fidelity":"F2","id":"zvt571v","kind":"sentence","match_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e","node_hash":"8a2293448ea48f2d3e279e609965f34443fae62b24b6fa13524f14a324749285","ord":0,"own_hash":"7c40e5ddd02d461a4ee50cde05532932e1d737ab3bc74b722cecf16cc6ffe59b","parent":"wxsngqp","prov":{"backend":"typst reader (illustrative)","witnesses":["tszzg52"]},"text_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e"} +{"align_key":"e9f8aaa4f05b10a153d268295a96c6adb2c39164a98b93eb1927e00838afe1fc","id":"x9ryw92","kind":"paragraph","match_hash":"e506663279fb3bebf3612dc69a36f5e090228abc0197f5228d4f0bd4abd47812","node_hash":"b17dff0cff3ce730e52efca92b9fe585ffc956cc9f76e52a8b37721cbbec442f","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"tqcsy8w","text_hash":"844954fa39d218228b947367bc95f21c449b4d70d1521a7f016e308643e6cf48"} +{"align_key":"7dc562c54f1b1cc46e472838c4b2d7c97b3e1b4d39172628d6607b0f2d313c3e","content":[{"kind":"text","text":"The bond term is harmonic in the bond length."}],"fidelity":"F2","id":"kda5wym","kind":"sentence","match_hash":"8f22f3f58beb618723a14dd8fee8caaeb5cef6b26f43d88a5ddb4ff42f86d63e","node_hash":"dd438a68616e63fd1cd5050d308779af58dfed2b4d43cc5a4bbab3fc8d4f2bcb","ord":0,"own_hash":"46dfbddc0e456a2b7f4105b8d3636220ff9145acccf3bdf81a206f0b84f95b63","parent":"x9ryw92","prov":{"backend":"typst reader (illustrative)","witnesses":["tszzg52"]},"text_hash":"8f22f3f58beb618723a14dd8fee8caaeb5cef6b26f43d88a5ddb4ff42f86d63e"} +{"align_key":"81422dae1385acfea463f7b7c75962de0bf92671d970a6ae9643763a8f87cd7f","content":[{"kind":"text","text":"Its constants come from a two-step fit "},{"kind":"xref","target":"hale2026harmonic-damb#a4jrz2t","text":"(Hale and Osei, Table 1)"},{"kind":"text","text":"."},{"kind":"cite","refs":["ebcq5cy"],"text":"1"}],"fidelity":"F2","id":"qgh1k31","kind":"sentence","match_hash":"fe82fa8560942e052e31d9b18cc8d3a9ba54ce01d91b66538ded6ff682a4e885","node_hash":"93a39490870e694299e88e6f475d42c38078d1442959e555bdbdf58488dcf187","ord":1,"own_hash":"e004436e7b28ff3dc41e0056f231ba707d9be985694e68acb911345a547842ed","parent":"x9ryw92","prov":{"backend":"typst reader (illustrative)","witnesses":["tszzg52"]},"text_hash":"0d5b27a20da22922ba0c5b65e06581a09d60b899e6daddc63b0e9c1dd3819055"} +{"align_key":"fae2fe63ef00f3826f525b2fd7f5c29824c06c1461b0a648927598f1efc84bc0","content":[{"kind":"text","text":"In that fit the energy is "},{"kind":"math","notation":"typst","source":"E = K_r (r - r_\"eq\")^2"},{"kind":"text","text":", up to a constant factor."}],"fidelity":"F2","id":"wbntyy4","kind":"sentence","match_hash":"9b297e00b7348c2df4c6b12f67b2f879217a0d71e1be382fc8a4f6bd7439ddd0","node_hash":"18b4b664473aeccb797c3c52b0d3fc3c37a33593d3aca32640acdb40161fa3e2","ord":2,"own_hash":"7ae59942b690f78ed24570ba25764a8b13239067437c6546622ebe701d55aee1","parent":"x9ryw92","prov":{"backend":"typst reader (illustrative)","witnesses":["tszzg52"]},"text_hash":"3873ff52fe20b52be605c10c11e78b24bcabb05c8f725aeb4820c23428631509"} +{"align_key":"a7226a2c68503d064f16cae87f6e01d25e5c75664bc8dee2d68ee2dc8c9f0c65","id":"hbb210j","kind":"back","match_hash":"5333f67a9eca4bf08b7c5bd643168084dddf40c175d8620dad293ff976a0ca31","node_hash":"a42481d70d840a9e15c3a5c31b9bfe503a78633c6b6431d3dc84dcd21b2f3019","ord":2,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"eaaw8zs","text_hash":"b652c2e642345a7363119a8e2b95154e29eee21a3dacefc147a9cc6cd1731316"} +{"align_key":"a7226a2c68503d064f16cae87f6e01d25e5c75664bc8dee2d68ee2dc8c9f0c65","id":"t728ktw","kind":"references","match_hash":"5333f67a9eca4bf08b7c5bd643168084dddf40c175d8620dad293ff976a0ca31","node_hash":"f25fb824a77ea0b61566aa32083103f6045473eeea053361f16d15127143e7e4","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"hbb210j","text_hash":"b652c2e642345a7363119a8e2b95154e29eee21a3dacefc147a9cc6cd1731316"} +{"align_key":"a7226a2c68503d064f16cae87f6e01d25e5c75664bc8dee2d68ee2dc8c9f0c65","content":[{"kind":"text","text":"1. R. Hale and M. Osei, J. Example Chem. 2026, 14, 101–109."}],"fidelity":"F2","id":"ebcq5cy","kind":"reference","label":"1","match_hash":"5333f67a9eca4bf08b7c5bd643168084dddf40c175d8620dad293ff976a0ca31","node_hash":"88c4043a1c30e4bec8f9fdbdd98922289d3f4224168da680d1582b96743ac053","ord":0,"own_hash":"6dc3f27fb4a4d7176f24c9de291095202c357030c173f1f9f2d9295929ae5f84","parent":"t728ktw","prov":{"backend":"typst reader (illustrative)","witnesses":["tszzg52"]},"text_hash":"b652c2e642345a7363119a8e2b95154e29eee21a3dacefc147a9cc6cd1731316"} diff --git a/fixtures/packages/writer2027fixed-ynr7.v3/provenance.json b/fixtures/packages/writer2027fixed-ynr7.v3/provenance.json new file mode 100644 index 0000000..961e28b --- /dev/null +++ b/fixtures/packages/writer2027fixed-ynr7.v3/provenance.json @@ -0,0 +1 @@ +{"note":"Built by hand for the conformance suite; every reading is synthetic.","stages":[{"processor":"local","stage":"hand","tool":"paperspec tools/build.py"}],"tools":[{"name":"paperspec tools/build.py","version":"0.1.0"}]} diff --git a/fixtures/packages/writer2027fixed-ynr7.v3/references.jsonl b/fixtures/packages/writer2027fixed-ynr7.v3/references.jsonl new file mode 100644 index 0000000..fc98a5f --- /dev/null +++ b/fixtures/packages/writer2027fixed-ynr7.v3/references.jsonl @@ -0,0 +1 @@ +{"csl":{"DOI":"10.5555/example.hale.2026","author":[{"family":"Hale","given":"R."},{"family":"Osei","given":"M."}],"container-title":"J. Example Chem.","issued":{"date-parts":[[2026]]},"page":"101-109","type":"article-journal","volume":"14"},"label":"1","node":"ebcq5cy","resolution":{"doc":"smithlab/hale2026harmonic-damb","type":"document"}} diff --git a/fixtures/packages/writer2027fixed-ynr7.v3/witnesses.json b/fixtures/packages/writer2027fixed-ynr7.v3/witnesses.json new file mode 100644 index 0000000..c1f4b52 --- /dev/null +++ b/fixtures/packages/writer2027fixed-ynr7.v3/witnesses.json @@ -0,0 +1 @@ +{"witnesses":[{"id":"tszzg52","kind":"typst","media_type":"application/zip","origin":{"source":"team"},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The team's own draft."}]},"at":"2026-09-15T12:00:00Z","basis":"own-work","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},"sha256":"aacfff02894cb87cfdb6ed973241ed30a5b59f380663fb264b14b4e06e1a3725","size":4211,"version_label":"draft 3"}]} diff --git a/fixtures/records/anchor-cell.json b/fixtures/records/anchor-cell.json new file mode 100644 index 0000000..d3173fa --- /dev/null +++ b/fixtures/records/anchor-cell.json @@ -0,0 +1 @@ +{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","quote":{"exact":"310.0"},"rev":12,"store":"smithlab"} diff --git a/fixtures/records/anchor-keyed.json b/fixtures/records/anchor-keyed.json new file mode 100644 index 0000000..47bae5c --- /dev/null +++ b/fixtures/records/anchor-keyed.json @@ -0,0 +1 @@ +{"context":{"column_path_mac":["8de5d9cfdf71c50b161f357ab526bc7ffadd407c49c642a10112bb41cc4e1bc1","31824d3d0594c075074ff3a88e4c571e1f856218179a809f4f69bd5891ee7ff8"],"row_path_mac":["1db463578fc748d9686a5a1355c2a08086f4f331b546ec3273dd5e49ff1d178d","74bdccbc71693a4f8046f2e92bc477ff04fc5e04a8998e3ee189ba6b72b971e0"],"table_label_mac":"6943d614b69c7b2458c337ead13591262e932934151c27862ec0d47e4d560641"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","keyed":{"algorithm":"sha-256","context":"layer:smithlab/kp4m2x7q","pages":["9dd865c7a19b44dc97a5d236859ed79174b25b72a5781d8df4f091d096de8908","1feb6882031349ca5eee822557bab0b6b0436a2d132ae8ca03babac2ff1948b8"],"scheme":"hkdf-pages"},"kind":"cell","node":"c20cna6","node_hash":"3efa98f63b493f7ba3ed01153859d3e0069fc39e1c51078b1239dedf0a4fc601","own_hash":"7bad196fc9634da03db3e418dfad50aa6b193acf9047e31db8908d9466c5ba40","quote":{"length":5,"mac":"0d8d4fcd55f1a4cfd7f254d597b7a5777b8865eb371283c03527ac8195ebb5ac"},"rev":12,"store":"smithlab"} diff --git a/fixtures/records/anchor-leaf.json b/fixtures/records/anchor-leaf.json new file mode 100644 index 0000000..4f9a381 --- /dev/null +++ b/fixtures/records/anchor-leaf.json @@ -0,0 +1 @@ +{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"rr20tev","node_hash":"76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7","own_hash":"2d7df7b8b233eab6f96d5db0d29c99062aaa94b55cf4e388c49b9995ce7548d5","quote":{"exact":"The bond energy is given by $$E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2$$ where $K_r$ is the bond force constant and $r_\\mathrm{eq}$ the equilibrium bond length."},"rev":12,"store":"smithlab"} diff --git a/fixtures/records/anchor-paragraph.json b/fixtures/records/anchor-paragraph.json new file mode 100644 index 0000000..46d1620 --- /dev/null +++ b/fixtures/records/anchor-paragraph.json @@ -0,0 +1 @@ +{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"paragraph","leaves":[["kea5026","83edd3a8c2b7d55b524ec0668beb74cceb3dcfb24dae5ff24e99d4c7b498e29a"],["rr20tev","924426976d176b8b8bb6a166c9f18d9c52225b47c1f5e17b68f0a36326f721d0"],["tkxsmts","cd2822e88bcde089a4b8d4d60820a4c0c387d75c7fb1737b5e5ac93129194ff7"],["hca6dc5","1306aa85965bf549361dbb25337341ad6caa1645f52fbf8bf72378988318ab59"]],"node":"tgp1qey","node_hash":"107c312588366cda7106e97f4ba67b9f3f417a2f0309e46d4d2e2513fe7be3c2","own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","rev":12,"store":"smithlab"} diff --git a/fixtures/records/anchor-span.json b/fixtures/records/anchor-span.json new file mode 100644 index 0000000..37073ac --- /dev/null +++ b/fixtures/records/anchor-span.json @@ -0,0 +1 @@ +{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"hca6dc5","node_hash":"8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34","own_hash":"c270571517825ceed31ca912b80ac76203effe47f1c84f8ee8962800d0afc92f","quote":{"exact":"first test case","prefix":"Water, H$_2$O, served as the ","suffix":", with a bending band near 1595 "},"rev":12,"span":[29,44],"store":"smithlab"} diff --git a/fixtures/records/backend-docling.json b/fixtures/records/backend-docling.json new file mode 100644 index 0000000..38ebb3b --- /dev/null +++ b/fixtures/records/backend-docling.json @@ -0,0 +1 @@ +{"code_license":{"spdx":"MIT"},"conditions":[],"format":"scienting-backend/1","name":"docling","processor":"local","stage":"read","version":"illustrative","weights":[{"license":{"spdx":"Apache-2.0"},"name":"layout model"}]} diff --git a/fixtures/records/backend-examplevendor.json b/fixtures/records/backend-examplevendor.json new file mode 100644 index 0000000..eb7fa5d --- /dev/null +++ b/fixtures/records/backend-examplevendor.json @@ -0,0 +1 @@ +{"code_license":{"spdx":"Apache-2.0"},"conditions":[{"id":"revenue-cap","kind":"revenue-cap","usd":5000000},{"id":"no-competition","kind":"no-competition","vendor":"examplevendor"},{"allowed":["research","personal","education","startup"],"id":"purpose","kind":"purpose"}],"format":"scienting-backend/1","name":"examplevendor","processor":"local","stage":"read","version":"1.0","weights":[{"license":{"text":"A fictional weight license with conditions."},"name":"example weights"}]} diff --git a/fixtures/records/checklist/checklist.json b/fixtures/records/checklist/checklist.json new file mode 100644 index 0000000..49b5cd2 --- /dev/null +++ b/fixtures/records/checklist/checklist.json @@ -0,0 +1 @@ +{"at":"2026-10-12T11:00:00Z","by":"ana","doc":"smithlab/hale2026harmonic-damb","export":{"kind":"html","sha256":"acc86ee7ee8343689fb1860e0b309cfc13f9538333cc45506eeb60db4db63faf","size":48213},"format":"scienting-checklist/1","id":"zaxj5a8amy53t","items":[{"criterion":"1.1.1","method":"manual","note":"Every figure has a confirmed description in the layer.","result":"pass"},{"criterion":"1.2.1","method":"manual","note":"No audio or video.","result":"not-applicable"},{"criterion":"1.3.1","method":"manual","note":"Headings, lists and table headers are marked up; each cell names its header path.","result":"pass"},{"criterion":"1.3.2","method":"automated","result":"pass","tool":{"name":"example-checker","version":"1.0"}},{"criterion":"1.4.3","method":"automated","result":"pass","tool":{"name":"example-checker","version":"1.0"}},{"criterion":"1.4.5","method":"manual","note":"Equations are MathML, never images of text.","result":"pass"},{"criterion":"2.4.2","method":"automated","result":"pass","tool":{"name":"example-checker","version":"1.0"}},{"criterion":"3.1.1","method":"automated","result":"pass","tool":{"name":"example-checker","version":"1.0"}}],"rev":12,"standard":{"level":"AA","name":"WCAG 2.1","url":"https://www.w3.org/TR/WCAG21/"}} diff --git a/fixtures/records/checklist/receipt.json b/fixtures/records/checklist/receipt.json new file mode 100644 index 0000000..982ee28 --- /dev/null +++ b/fixtures/records/checklist/receipt.json @@ -0,0 +1 @@ +{"at":"2026-10-12T11:30:00Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"source-file","note":"The exported HTML.","sha256":"acc86ee7ee8343689fb1860e0b309cfc13f9538333cc45506eeb60db4db63faf"}],"format":"scienting-receipt/1","id":"v4x79ek29ctb1","level":"F3","nodes":[],"records":[["checklist","zaxj5a8amy53t","835764552154f147a18865d0713488323933528633105874c3c1e9e805a3aa2e"]],"rev":12,"root":"54f66670480886677ac381907604ed6c9dfef97b4e5d4a1b955748fe41296bd6","scope":"targeted:checklist","signature":{"key":"ana","scheme":"ed25519","value":"ttzZTfAay7O2EEtXw9KXlo6389H6kpVqsA6DXTPA/LdEErJ6SzC61ek2Nb2ZIOsddarMkbWVY7ydwmoy1q6eBA=="}} diff --git a/fixtures/records/checkpoint.json b/fixtures/records/checkpoint.json new file mode 100644 index 0000000..94e9fec --- /dev/null +++ b/fixtures/records/checkpoint.json @@ -0,0 +1 @@ +{"format":"scienting-checkpoint/1","note":"scient.ing/log/smithlab\n9\nGa0n103p3Gl136z6XWmM92kGvsvMYGXlk+ijjX4KWiA=\n\n— ana dBv7wtCAdNnczkCO5KwtrmDvtWUVPRusBSuLPeBDQoLZi9Hm34IHuNjvnjyPEar5afNf7xqcDtokk2XZEP31uJMVuwE=\n— wit h7ghDsJGkhWLaPO7+TIZQUenslhiQh/E/TKWU4ddphpFcuylQBZM2kG/o8H1nyPfUT0MkbvnFqPFfHPH3OaN5W1EwAI=\n","origin":"scient.ing/log/smithlab","root":"19ad27d74de9dc6975dfacfa5d698cf76906becbcc6065e593e8a38d7e0a5a20","signatures":[{"key_hash":"741bfbc2","name":"ana","value":"0IB02dzOQI7krC2uYO+1ZRU9G6wFK4s94ENCgtmL0ebfgge42O+ePI8Rqvlp81/vGpwO2iSTZdkQ/fW4kxW7AQ=="},{"key_hash":"87b8210e","name":"wit","value":"wkaSFYto87v5MhlBR6eyWGJCH8T9MpZTh12mGkVy7KVAFkzaQb+jwfWfI99RPQyRu+cWo8V8c8fc5o3lbUTAAg=="}],"size":9} diff --git a/fixtures/records/datasets/ds-hale-ctct-scan/anchors.jsonl b/fixtures/records/datasets/ds-hale-ctct-scan/anchors.jsonl new file mode 100644 index 0000000..94060e5 --- /dev/null +++ b/fixtures/records/datasets/ds-hale-ctct-scan/anchors.jsonl @@ -0,0 +1,6 @@ +{"digitization":"n43jx89tgmmzy","field":"r","point":0,"resource":"scan","row":"p0","series":"scan"} +{"digitization":"n43jx89tgmmzy","field":"e","point":0,"resource":"scan","row":"p0","series":"scan"} +{"digitization":"n43jx89tgmmzy","field":"r","point":1,"resource":"scan","row":"p1","series":"scan"} +{"digitization":"n43jx89tgmmzy","field":"e","point":1,"resource":"scan","row":"p1","series":"scan"} +{"digitization":"n43jx89tgmmzy","field":"r","point":2,"resource":"scan","row":"p2","series":"scan"} +{"digitization":"n43jx89tgmmzy","field":"e","point":2,"resource":"scan","row":"p2","series":"scan"} diff --git a/fixtures/records/datasets/ds-hale-ctct-scan/data.csv b/fixtures/records/datasets/ds-hale-ctct-scan/data.csv new file mode 100644 index 0000000..93509a7 --- /dev/null +++ b/fixtures/records/datasets/ds-hale-ctct-scan/data.csv @@ -0,0 +1,4 @@ +point,r,r_u,e,e_u +p0,1.45,0.01,3.10,0.05 +p1,1.50,0.01,0.40,0.05 +p2,1.55,0.01,2.80,0.05 diff --git a/fixtures/records/datasets/ds-hale-ctct-scan/datapackage.json b/fixtures/records/datasets/ds-hale-ctct-scan/datapackage.json new file mode 100644 index 0000000..3bc8b08 --- /dev/null +++ b/fixtures/records/datasets/ds-hale-ctct-scan/datapackage.json @@ -0,0 +1 @@ +{"format":"scienting-dataset/1","id":"ds-hale-ctct-scan","name":"hale-ctct-scan","resources":[{"encoding":"utf-8","format":"csv","name":"scan","origin":{"anchors":"anchors.jsonl","digitization":"n43jx89tgmmzy","kind":"digitized"},"path":"data.csv","schema":{"fields":[{"name":"point","type":"string"},{"name":"r","type":"number","uncertainty":{"field":"r_u","kind":"resolution"},"unit":"angstrom"},{"name":"r_u","type":"number","unit":"angstrom"},{"name":"e","type":"number","uncertainty":{"field":"e_u","kind":"resolution"},"unit":"kcal / mol"},{"name":"e_u","type":"number","unit":"kcal / mol"}],"primaryKey":"point"}}],"title":"Energy along the C–C stretch, read from Figure 1a"} diff --git a/fixtures/records/digitization-confirmation.json b/fixtures/records/digitization-confirmation.json new file mode 100644 index 0000000..59e6241 --- /dev/null +++ b/fixtures/records/digitization-confirmation.json @@ -0,0 +1 @@ +{"at":"2026-10-11T20:00:00Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"rzxn46v","sha256":"41859f0385275a8386eef230d92fc34a379549dd475f27396dc6e8a94ca0fc54"}],"format":"scienting-receipt/1","id":"s91x847fmg0gg","level":"F3","nodes":[],"records":[["digitization","n43jx89tgmmzy","b49029057a26af378a97fc1e740801f767934e49161e867ec552700e8eff75bc"]],"rev":12,"root":"8ec8914c43871ac949b14221bb71a145e484f80d6c169ec639efedffc3ed7979","scope":"targeted:digitization","signature":{"key":"ana","scheme":"ed25519","value":"2Gdqmv/PzL7j21NxSHprM8PgJtFQxI6L+pNkjV53RfMNJjEHRZfOnB9nVOzDfCJnGWuTvCS8+T9Qg6WapF60AQ=="}} diff --git a/fixtures/records/digitization.json b/fixtures/records/digitization.json new file mode 100644 index 0000000..db2ab25 --- /dev/null +++ b/fixtures/records/digitization.json @@ -0,0 +1 @@ +{"axes":[{"calibration":[{"at":[90,400],"value":"1.4"},{"at":[210,400],"value":"1.6"}],"check":{"at":[150,400],"value":"1.5"},"id":"x","label":{"figure_text":"rtxzjj9","panel":"rzxn46v"},"scale":"linear","unit":"angstrom"},{"calibration":[{"at":[80,400],"value":"0"},{"at":[80,280],"value":"4"}],"id":"y","label":{"figure_text":"f31xtb6","panel":"rzxn46v"},"scale":"linear","unit":"kcal / mol"}],"confirmation":null,"dataset":"ds-hale-ctct-scan","doc":"smithlab/hale2026harmonic-damb","format":"scienting-digitization/1","id":"n43jx89tgmmzy","method":{"kind":"manual","tool":{"name":"hand","version":"0"}},"rev":12,"series":[{"id":"scan","kind":"points","legend":"scan","mark":{"color":"#285aa0","marker":"circle"},"values":[{"at":[110,360],"uncertainty":{"calibration":"0.01","marker":"0.02","resolution":"0.01","x":"0.01","y":"0.05"},"value":{"x":"1.45","y":"3.10"}},{"at":[150,330],"uncertainty":{"calibration":"0.01","marker":"0.02","resolution":"0.01","x":"0.01","y":"0.05"},"value":{"x":"1.50","y":"0.40"}},{"at":[190,300],"uncertainty":{"calibration":"0.01","marker":"0.02","resolution":"0.01","x":"0.01","y":"0.05"},"value":{"x":"1.55","y":"2.80"}}]}],"target":{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"panel","node":"rzxn46v","node_hash":"72ab6d60a594c2fdcb20bcc7142bd8e83d36046ef817c61d4240a93e5523e4aa","own_hash":"95cd7f9ab50d8386dc3086cf45a377c1d25c6c6111e3c422b69af10b6b1828c6","rev":12,"store":"smithlab"},"page_fp":"128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60","region":[72,260,300,410],"witness":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"},"verification":{"image":"41859f0385275a8386eef230d92fc34a379549dd475f27396dc6e8a94ca0fc54","max_residual":"0.9","residual":"0.4"}} diff --git a/fixtures/records/draft-ids.jsonl b/fixtures/records/draft-ids.jsonl new file mode 100644 index 0000000..9218f7f --- /dev/null +++ b/fixtures/records/draft-ids.jsonl @@ -0,0 +1,5 @@ +{"id":"csgs20p","ord":0,"section":null,"text_hash":"d3c3de666d0290878de3949bc0e0ffcaef965c66d2b61e81a5e615e26a2997df"} +{"id":"zvt571v","ord":0,"section":"tqcsy8w","text_hash":"b605350bc00209520b7cd8f546322663356ba630708f71bbf30aead6b3dd608e"} +{"id":"kda5wym","ord":0,"section":"tqcsy8w","text_hash":"8f22f3f58beb618723a14dd8fee8caaeb5cef6b26f43d88a5ddb4ff42f86d63e"} +{"id":"qgh1k31","ord":1,"section":"tqcsy8w","text_hash":"0d5b27a20da22922ba0c5b65e06581a09d60b899e6daddc63b0e9c1dd3819055"} +{"id":"wbntyy4","ord":2,"pinned":"energy-sentence","section":"tqcsy8w","text_hash":"3873ff52fe20b52be605c10c11e78b24bcabb05c8f725aeb4820c23428631509"} diff --git a/fixtures/records/grades/anchor-hit.json b/fixtures/records/grades/anchor-hit.json new file mode 100644 index 0000000..f99fc93 --- /dev/null +++ b/fixtures/records/grades/anchor-hit.json @@ -0,0 +1 @@ +{"exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-grade/1","items":[{"element":"element:0","feedback":"That is the cell.","max":"1","points":"1"}],"max":"1","score":"1","submission":"kpjevbt3j6s3w"} diff --git a/fixtures/records/grades/anchor-miss.json b/fixtures/records/grades/anchor-miss.json new file mode 100644 index 0000000..09513b4 --- /dev/null +++ b/fixtures/records/grades/anchor-miss.json @@ -0,0 +1 @@ +{"exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-grade/1","items":[{"element":"element:0","feedback":"Look in Table 1, row CT–CT.","max":"1","points":"0"}],"max":"1","score":"0","submission":"ysw9hjztre498"} diff --git a/fixtures/records/grades/check-overlap.json b/fixtures/records/grades/check-overlap.json new file mode 100644 index 0000000..9c4fe28 --- /dev/null +++ b/fixtures/records/grades/check-overlap.json @@ -0,0 +1 @@ +{"exercise":"tag:scient.ing,2026:annotation:smithlab/y7bd3he0jwjbx","format":"scienting-grade/1","items":[{"element":"verdict","feedback":"","max":"1","points":"1"},{"element":"element:0","feedback":"","max":"1","points":"1"}],"max":"2","score":"2","submission":"n7me2fmcw8ree"} diff --git a/fixtures/records/layer/annotations.jsonl b/fixtures/records/layer/annotations.jsonl new file mode 100644 index 0000000..250fcd2 --- /dev/null +++ b/fixtures/records/layer/annotations.jsonl @@ -0,0 +1,10 @@ +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"audience":"novice","format":"text/markdown","kind":"gloss","language":"en","type":"TextualBody","value":"A *harmonic* term treats a bond like a spring: the energy grows with the square of the stretch."},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/f4s8pc1hdhd9d","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"describing","receipt":"r10e5mzvw6tja","status":"confirmed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"rr20tev","node_hash":"76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7","own_hash":"2d7df7b8b233eab6f96d5db0d29c99062aaa94b55cf4e388c49b9995ce7548d5","quote":{"exact":"bond force constant","prefix":"rm{eq}})^2$$ where $K_r$ is the ","suffix":" and $r_\\mathrm{eq}$ the equilib"},"rev":12,"span":[111,130],"store":"smithlab"},"type":"AnchorSelector"},{"exact":"bond force constant","prefix":"rm{eq}})^2$$ where $K_r$ is the ","suffix":" and $r_\\mathrm{eq}$ the equilib","type":"TextQuoteSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"kind":"claim-link","pin":"illustrative-pin","role":"states","source":"lode:amber/k-bond","type":"SpecificResource"},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/nzwtq23khdx4s","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"linking","receipt":"r10e5mzvw6tja","status":"confirmed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"rr20tev","node_hash":"76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7","own_hash":"2d7df7b8b233eab6f96d5db0d29c99062aaa94b55cf4e388c49b9995ce7548d5","quote":{"exact":"The bond energy is given by $$E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2$$ where $K_r$ is the bond force constant and $r_\\mathrm{eq}$ the equilibrium bond length."},"rev":12,"store":"smithlab"},"type":"AnchorSelector"},{"exact":"The bond energy is given by $$E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2$$ where $K_r$ is the bond force constant and $r_\\mathrm{eq}$ the equilibrium bond length.","prefix":"","suffix":"","type":"TextQuoteSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"kind":"comment","type":"TextualBody","value":"The step size matters more than the text admits."},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/m9e0g8r5ebnkf","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"commenting","status":"proposed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"xjns57z","node_hash":"42b1de7852cdc68730984fff789fe248ecd5b43198c0e7d671931ff3fe561dc3","own_hash":"4dc28d1ad57c74d044f87264dfbc744ae9d5e9644638db976dbc346361442486","quote":{"exact":"steps of 0.01","prefix":"Each bond was scanned in ","suffix":" Å around its minimum, and the e"},"rev":12,"span":[25,38],"store":"smithlab"},"type":"AnchorSelector"},{"exact":"steps of 0.01","prefix":"Each bond was scanned in ","suffix":" Å around its minimum, and the e","type":"TextQuoteSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"for":"group","kind":"question","type":"TextualBody","value":"Why fit to a scan first and to frequencies second?"},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/x0emxkxem54hw","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"questioning","status":"proposed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"section","node":"d400rz3","node_hash":"e5a8eeb3c112f2dc3341da8f433540a3fc5a7e7f631e72c4dd36c6933aae808d","own_hash":"c3d50f266b05d7889c001aef16662cecd4e99ac4a2747ec331c1044e6adc8e3e","rev":12,"store":"smithlab"},"type":"AnchorSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"kind":"citation-context","reason":"value","reference":"vxsdvzq","type":"TextualBody","value":"Cited for the band position; the reference is not in the library.","verdict":"cannot-tell"},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/gbj7nn87ndfd8","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"assessing","status":"proposed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"hca6dc5","node_hash":"8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34","own_hash":"c270571517825ceed31ca912b80ac76203effe47f1c84f8ee8962800d0afc92f","quote":{"exact":"1595","prefix":" case, with a bending band near ","suffix":" cm⁻¹.2"},"rev":12,"span":[71,75],"store":"smithlab"},"type":"AnchorSelector"},{"exact":"1595","prefix":" case, with a bending band near ","suffix":" cm⁻¹.2","type":"TextQuoteSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"generator":{"model":{"name":"example-model","parameters":"998b5161e39e01c8bc43ef81ec89141e15b7ea53b2e936707920a6097dbcb2c5","processor":"local","prompt":"9cc338fba7c62db7266f530cb555a5ee36910d41a0120a3fe7fd7de1944d0931","provider":"Example Models (illustrative)","version":"2026-09","weights":"504b2d340045b92c22682b60020c21103aae7ff41172bb632fbe305eb4af9b5e"},"run":"illustrative-run-1"},"kind":"generated","type":"TextualBody","value":"Two panels: an energy scan and its fit residual."},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:software:example-model","name":"A model (illustrative)","type":"Software"},"id":"tag:scient.ing,2026:annotation:smithlab/szb6k3fj9z7aw","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"describing","status":"proposed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"figure","node":"v7cx6qs","node_hash":"f76864779843485fa9e2f3cc3cd1c76ad222e1649c56f4cface33bf20b8f33b6","own_hash":"a1e46cb40201a17903dfd6f128db1e707b0e9f5bf45fcc32ec7ca772011edeae","rev":12,"store":"smithlab"},"type":"AnchorSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"exercise":{"exercise":"anchor","format":"scienting-exercise/1","key":{"elements":[{"anchors":[{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","quote":{"exact":"310.0"},"rev":12,"store":"smithlab"}],"feedback":{"hit":"That is the cell.","miss":"Look in Table 1, row CT–CT."},"points":"1"}]},"prompt":"Find the table cell that gives the Set A bond constant for the CT–CT bond.","rule":{"match":"same-node"}},"kind":"exercise","type":"TextualBody","value":"Find the table cell that gives the Set A bond constant for the CT–CT bond."},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"assessing","receipt":"r10e5mzvw6tja","status":"confirmed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"table","node":"hj4s7pb","node_hash":"6c6fba200faf41cd06fa8b64e06e2aa29ff8848568b859ae42d1902596348643","own_hash":"66310a9ab1c92568f4c6cae012e35d4245d4ca4b89d2542b7c2113a31ad379ed","rev":12,"store":"smithlab"},"type":"AnchorSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"exercise":{"exercise":"check","format":"scienting-exercise/1","key":{"elements":[{"anchors":[{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"kea5026","node_hash":"b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33","own_hash":"d673d236c03d9583ecf6e01fa819765ec324dc684bd9bbc6967fa50f216e34d2","quote":{"exact":"the most common description","prefix":"Harmonic bond terms remain ","suffix":" of covalent stretching in class"},"rev":12,"span":[27,54],"store":"smithlab"}],"points":"1"}],"verdict":{"points":"1","value":"supports"}},"prompt":"Does the cited passage support the claim that harmonic terms are the most common choice?","rule":{"match":"overlap","min_overlap":"0.5"}},"kind":"exercise","type":"TextualBody","value":"Does the cited passage support the claim that harmonic terms are the most common choice?"},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/y7bd3he0jwjbx","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"assessing","receipt":"r10e5mzvw6tja","status":"confirmed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"kea5026","node_hash":"b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33","own_hash":"d673d236c03d9583ecf6e01fa819765ec324dc684bd9bbc6967fa50f216e34d2","quote":{"exact":"Harmonic bond terms remain the most common description of covalent stretching in classical force fields.1"},"rev":12,"store":"smithlab"},"type":"AnchorSelector"},{"exact":"Harmonic bond terms remain the most common description of covalent stretching in classical force fields.1","prefix":"","suffix":"","type":"TextQuoteSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"kind":"description","language":"en","role":"alt","type":"TextualBody","value":"Energy along the C–C bond stretch (panel a) and the fit residual (panel b)."},"created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/gb5tmv3hq08vz","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"describing","receipt":"r10e5mzvw6tja","status":"confirmed","target":{"selector":[{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"figure","node":"v7cx6qs","node_hash":"f76864779843485fa9e2f3cc3cd1c76ad222e1649c56f4cface33bf20b8f33b6","own_hash":"a1e46cb40201a17903dfd6f128db1e707b0e9f5bf45fcc32ec7ca772011edeae","rev":12,"store":"smithlab"},"type":"AnchorSelector"}],"source":"tag:scient.ing,2026:doc:smithlab/hale2026harmonic-damb","type":"SpecificResource"},"type":"Annotation"} +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"body":{"kind":"comment","type":"TextualBody","value":"Agreed; see the residual panel."},"created":"2026-10-11T19:05:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"id":"tag:scient.ing,2026:annotation:smithlab/j3vr50xm97cp7","layer":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","motivation":"replying","status":"proposed","target":{"source":"tag:scient.ing,2026:annotation:smithlab/m9e0g8r5ebnkf","type":"SpecificResource"},"type":"Annotation"} diff --git a/fixtures/records/layer/layer.json b/fixtures/records/layer/layer.json new file mode 100644 index 0000000..fac3dc6 --- /dev/null +++ b/fixtures/records/layer/layer.json @@ -0,0 +1 @@ +{"@context":["http://www.w3.org/ns/anno.jsonld","https://paperspec.scient.ing/context/scienting-1.jsonld"],"audience":"student","created":"2026-10-11T19:00:00Z","creator":{"id":"tag:scient.ing,2026:key:ana","name":"Ana Example","type":"Person"},"docs":["smithlab/hale2026harmonic-damb"],"format":"scienting-layer/1","id":"tag:scient.ing,2026:layer:smithlab/kp4m2x7q","label":"Smith lab reading of Hale and Osei","license":{"spdx":"CC-BY-4.0"},"project":"smithlab-charges","purpose":"Glosses, claim links and exercises for new students.","total":10,"type":"AnnotationCollection","visibility":"team"} diff --git a/fixtures/records/layer/receipt.json b/fixtures/records/layer/receipt.json new file mode 100644 index 0000000..962ccac --- /dev/null +++ b/fixtures/records/layer/receipt.json @@ -0,0 +1 @@ +{"at":"2026-10-11T19:30:00Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[],"format":"scienting-receipt/1","id":"r10e5mzvw6tja","level":"F3","nodes":[],"records":[["annotation","f4s8pc1hdhd9d","9db553d2150a912e4ba3027d002706e08ccaded843d3e49c79b95a2e0581b6f1"],["annotation","gb5tmv3hq08vz","3b776d37af21d1bdfd3a0130c9bfa26affa484fb4d76e41d83cbd8bb02b4975c"],["annotation","nzwtq23khdx4s","8ea94b7a3d266f51e11dd31399784019acd1b1b53ed093e15c199417327992ab"],["annotation","whcypxav2cqbx","11845db3ef685b0b9bd13895cc5b8ade5b345ee7d72737a630be60d690a2ba5d"],["annotation","y7bd3he0jwjbx","0286ede04d8bf548432e34dd7beeee0fb044bd43022a8661a292018dd2ef5578"]],"rev":12,"root":"246581b0926273458b78ece15b465f0567c150a1e071f72322ce41895f9502e1","scope":"targeted:layer","signature":{"key":"ana","scheme":"ed25519","value":"WMDdARYwB0ETltF57ks1MxJ6ny/c4XziLvYUBd8PoW7MwcfhPKmDTqNGxRNg4z5g4c/bHnWS4ftZLJiONTL/Cg=="}} diff --git a/fixtures/records/log/checkpoint b/fixtures/records/log/checkpoint new file mode 100644 index 0000000..b37b0a2 --- /dev/null +++ b/fixtures/records/log/checkpoint @@ -0,0 +1,6 @@ +scient.ing/log/smithlab +9 +Ga0n103p3Gl136z6XWmM92kGvsvMYGXlk+ijjX4KWiA= + +— ana dBv7wtCAdNnczkCO5KwtrmDvtWUVPRusBSuLPeBDQoLZi9Hm34IHuNjvnjyPEar5afNf7xqcDtokk2XZEP31uJMVuwE= +— wit h7ghDsJGkhWLaPO7+TIZQUenslhiQh/E/TKWU4ddphpFcuylQBZM2kG/o8H1nyPfUT0MkbvnFqPFfHPH3OaN5W1EwAI= diff --git a/fixtures/records/log/tile/0/000.p/9 b/fixtures/records/log/tile/0/000.p/9 new file mode 100644 index 0000000..e016415 Binary files /dev/null and b/fixtures/records/log/tile/0/000.p/9 differ diff --git a/fixtures/records/log/tile/entries/000.p/9 b/fixtures/records/log/tile/entries/000.p/9 new file mode 100644 index 0000000..1fe80ae --- /dev/null +++ b/fixtures/records/log/tile/entries/000.p/9 @@ -0,0 +1,9 @@ +["receipt","npc15pn6675z5","37b3025b54c6397e5f8d400912b5788cd6ce203059cd9143e7d521c2cdbf2917"] +["receipt","y2zw8ctg5s8dp","ae17f8866a05ca1b671d96b7758984e11ac694acd6743835f107cb513c7cc600"] +["receipt","mvjmb94nz7rdh","a4dca8b492bf3e1b190f22e09de77713523e345526fd1b01c1186d0fe80d1cf4"] +["receipt","q465jpwz8afhe","39218b2b73e853e2e66d8d4ce68cf7e155ca001f05ee4da5942a8d9b63b216bc"] +["revocation","pcbhtpwvysgq6","9062e3ab737ecc2e6d487d2076ee27f764be60f06ad01f1ad103d708d466e56a"] +["receipt","gx2s84z9jf9xv","5ee8b2827d327a7bbcacb08fd19b9523fad83ebf6c29350d5ce7ca30bf5ce388"] +["receipt","mg18668nzxvap","4c80506322bfeed5649cfab303959e4ccf0aa0e594995ee6fd5ad59f9d3ee6a7"] +["receipt","yt70fcc3qm0xb","2ad1c0f63077a03ab1cce01e6235734577d0b072b90ebab2f7db7fd481ccee2c"] +["roster","smithlab","782c5e68f4e4f9918e69b7a44b108d9d70c89a289981acff3d25300ec8373c15"] diff --git a/fixtures/records/policy.json b/fixtures/records/policy.json new file mode 100644 index 0000000..ac75df6 --- /dev/null +++ b/fixtures/records/policy.json @@ -0,0 +1 @@ +{"applies_to":{"basis":["subscription"],"doi_prefixes":["10.5555/"]},"at":"2026-10-05T09:00:00Z","by":"ana","format":"scienting-policy/1","id":"g6r348z7ckp4q","project":"smithlab-charges","signature":{"key":"ana","scheme":"ed25519","value":"FLg+kUV7cf0v+t8tGkYEtKdEazsqBb7X2LTqRHmMXH3h3ue/SXiegRBFxgIKff28elJSFv5EG7dK9LqvOs+PAA=="},"statement":"Our institutional agreement covers internal AI use in our own cloud account for these papers (fictional).","uses":{"ai":{"internal/tenancy":true}},"valid_until":"2027-08-31T23:59:59Z"} diff --git a/fixtures/records/profile-acme.json b/fixtures/records/profile-acme.json new file mode 100644 index 0000000..cb1e8f8 --- /dev/null +++ b/fixtures/records/profile-acme.json @@ -0,0 +1 @@ +{"at":"2026-10-01T00:00:00Z","competes_with":null,"format":"scienting-profile/1","purpose":"commercial","recorded_by":"acme-admin","revenue_or_funding_usd":{"at_most":null},"team":"acme"} diff --git a/fixtures/records/profile-smithlab.json b/fixtures/records/profile-smithlab.json new file mode 100644 index 0000000..8791b3a --- /dev/null +++ b/fixtures/records/profile-smithlab.json @@ -0,0 +1 @@ +{"at":"2026-10-01T00:00:00Z","competes_with":[],"format":"scienting-profile/1","purpose":"research","recorded_by":"ana","revenue_or_funding_usd":{"at_most":2000000},"team":"smithlab"} diff --git a/fixtures/records/project.json b/fixtures/records/project.json new file mode 100644 index 0000000..87f9794 --- /dev/null +++ b/fixtures/records/project.json @@ -0,0 +1 @@ +{"claims":{"lode":"amber"},"datasets":["ds-hale-bond-params","ds-hale-ctct-scan"],"documents":[{"doc":"smithlab/hale2026harmonic-damb","reason":"The bond constants we start from.","status":{"Ben Example":"read","Cara Example":"reading"},"tags":["parameters"]},{"doc":"okafor2025solvent-acth","reason":"Solvent shifts for the validation set.","tags":["spectra"]}],"drafts":["smithlab/writer2027fixed-ynr7.v3"],"format":"scienting-project/1","key":"smithlab-charges","layers":["tag:scient.ing,2026:layer:smithlab/kp4m2x7q"],"members":[{"keys":["ana"],"person":"Ana Example","role":"owner"},{"keys":["ben","ben-spot"],"person":"Ben Example","role":"editor"},{"keys":["cara"],"person":"Cara Example","role":"reader"}],"name":"Charges and bonds","paths":[{"id":"onboarding","steps":[{"note":"Read the introduction.","ref":"smithlab/hale2026harmonic-damb","type":"document"},{"note":"Then the table.","ref":"smithlab/hale2026harmonic-damb#hj4s7pb","type":"node"},{"ref":"lode:amber/k-bond","type":"claim"}],"title":"First week"}],"settings":{"digit_rule":"anchored-sections","drift_threshold":"0.25","log":{"origin":"scient.ing/log/smithlab","threshold":1,"witnesses":["wit"]},"rights_unknown":"refuse","spot_check":{"minimum":10,"rate":"0.05"},"stages":"scienting-stages-default"},"store":"smithlab","views":["ctct-scan"]} diff --git a/fixtures/records/proof-consistency.json b/fixtures/records/proof-consistency.json new file mode 100644 index 0000000..7996743 --- /dev/null +++ b/fixtures/records/proof-consistency.json @@ -0,0 +1 @@ +{"doc":"smithlab/hale2026harmonic-damb","format":"scienting-proof/1","from_rev":8,"from_root":"1fd353414a872011b133a8d53d96bc193e45ac89721237c05da7a671ec09aa5b","kind":"consistency","path":["970d5333fabc81c33a34b524bb11a21aa6bc808fb15a4b954924d0058ddd69ff"],"to_rev":12,"to_root":"e215570ec1c660164c8b1e8012a9c7de9e98d5e508bf80ffdc2c7cd4cbb5ab0f"} diff --git a/fixtures/records/proof-inclusion.json b/fixtures/records/proof-inclusion.json new file mode 100644 index 0000000..2cd339b --- /dev/null +++ b/fixtures/records/proof-inclusion.json @@ -0,0 +1 @@ +{"format":"scienting-proof/1","index":3,"item":["node","c20cna6","c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272"],"kind":"inclusion","path":["1344d74efcc8182f2a1ac7501fc4a3b888bfd753b1cc9c4c02562d7d51b91a1d","be61b225edd17fe256a73b79b26c2be1e2cc43d370ba4c9e7f0536b12c305650","abe0ffd73517576e3c64411f54f854fb008b13a828695d1f9e3059cfb9bfd2cd","0497554cb70abf31d1bf919cf74b62652e21a5c4ed1875c951971ddada26bc3e","c352582a32865ce563529803845821c0227a85e06490dc069cb945a80fc9cfa9"],"receipt":"y2zw8ctg5s8dp","root":"373a7d860a14b58e5bfa9b9ad3bc916091bcb6db7556f0dbc9c71972a612494d","size":23} diff --git a/fixtures/records/qa-report.json b/fixtures/records/qa-report.json new file mode 100644 index 0000000..078e9c3 --- /dev/null +++ b/fixtures/records/qa-report.json @@ -0,0 +1 @@ +{"at":"2026-10-12T10:00:00Z","by":"ana","delivery":"smithlab evidence pilot (fictional)","docs":["smithlab/hale2026harmonic-damb"],"format":"scienting-qa-report/1","id":"b6dt4h4pv0x98","receipts":["y2zw8ctg5s8dp","gx2s84z9jf9xv"],"reviewers":[{"bound":"0.316340","confidence":"0.95","errors":1,"key":"ana","method":"clopper-pearson","sampled":13}],"signature":{"key":"ana","scheme":"ed25519","value":"7nFBiJ2csiX8Y0lgn3Tp5+7IKlMUMRfVEN3B3pdrgw3rCdEG2VXJaafoJ2lClb19Io2bMpfww3k0epkKfef/Dw=="}} diff --git a/fixtures/records/receipt-ml-dsa.json b/fixtures/records/receipt-ml-dsa.json new file mode 100644 index 0000000..5949a67 --- /dev/null +++ b/fixtures/records/receipt-ml-dsa.json @@ -0,0 +1 @@ +{"at":"2026-10-13T09:00:00Z","by":"dana","doc":"hale2026harmonic-damb","evidence":[{"by":"dana","kind":"person"}],"format":"scienting-receipt/1","id":"vbttn1qvxkx4s","level":"F2","nodes":[["kea5026","b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33"],["rr20tev","76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7"]],"rev":12,"root":"1529e715397aae9f44f1f17fb95c5ef8fbef008d901c2624413b899e8552b174","scope":"targeted:ml-dsa","signature":{"key":"dana","scheme":"ml-dsa-65","value":"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"}} diff --git a/fixtures/records/rights-collective.json b/fixtures/records/rights-collective.json new file mode 100644 index 0000000..88f1690 --- /dev/null +++ b/fixtures/records/rights-collective.json @@ -0,0 +1 @@ +{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"collective-license","format":"scienting-rights/1","license":{"text":"Annual collective license with internal AI re-use (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-06-30T23:59:59Z"} diff --git a/fixtures/records/rights-open.json b/fixtures/records/rights-open.json new file mode 100644 index 0000000..cdbe233 --- /dev/null +++ b/fixtures/records/rights-open.json @@ -0,0 +1 @@ +{"asserted_by":{"by":"crossref","evidence":[{"doi":"10.5555/example.okafor.2025","kind":"crossref-license","url":"https://creativecommons.org/licenses/by/4.0/"}]},"at":"2026-09-15T12:00:00Z","basis":"open-license","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0","url":"https://creativecommons.org/licenses/by/4.0/"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null} diff --git a/fixtures/records/rights-subscription.json b/fixtures/records/rights-subscription.json new file mode 100644 index 0000000..82880a0 --- /dev/null +++ b/fixtures/records/rights-subscription.json @@ -0,0 +1 @@ +{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"} diff --git a/fixtures/records/roster.json b/fixtures/records/roster.json new file mode 100644 index 0000000..36584ed --- /dev/null +++ b/fixtures/records/roster.json @@ -0,0 +1 @@ +{"format":"scienting-roster/1","keys":[{"did":"did:key:z6Mkj7iUX8QG7zkAtNaV78CUXcenhD87qWwQbc7NU5aVXyW9","id":"ana","person":{"name":"Ana Example"},"public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"owner","scheme":"ed25519"},{"did":"did:key:z6MkhemKN7rMQcgt6wT2eWPyx3vFRS1RUoRziLMnLq2vZ9yi","id":"ben","person":{"name":"Ben Example"},"public":"L4WMLs7xLjBLRsxS/EYpD194puMBpADybcfFEWxBkWk=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6MkrBf2w3MUroaNBiHTQJzH4e1w31jpcosd5vNxjikijndU","id":"ben-spot","person":{"name":"Ben Example"},"public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","purposes":["spot-check"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ed25519"},{"did":"did:key:z6Mkgrc9HCeEUL5tz1bVfuuDeSm6mP6hyWUX5ivhgReSbEQM","id":"cara","person":{"name":"Cara Example"},"public":"I7J1GqG5CHOc0LHYZPNNto1Me2lJUzBVn2A7GrUGbZ4=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"reader","scheme":"ed25519"},{"did":"did:key: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","id":"dana","person":{"name":"Dana Example"},"public":"lQ6M2DulKY4RkQLGTPGZD+CHlOOib4kBkwlccVNWRDPco1k5kHtelT/yUP4+CoAQnHnLu96vpeWztaee/9RmjR3bstGj+P5tOSrwFlPuyNUPOWPNjwCQLrVEyeUGBaA4+HRvFwK7C4OHB8EJWYtC0OuH+tRPlCdLpxlVcZZcM7dsZYe2BDNenbWfp4TeX2Oa+dThlceDY0m9MewwqUrd5xdo9tc8PS9R9o0ZUWf0vDw7Fc5AcsWwbf76lDLvIbyd0aCaHJ7eaK6DFsBuZFKVdlZlH0inJciAMF8dPoRuE+A0VlZTEOsOivNWprM5iLHzXse3zSoHLldWr0t4hWxHH3MBQ57Ucee8RTU6hFRfqfFRl6zJQyRZOFZZoYD9QwXkR3NmUzV/FcsOMHpbgTcY7O0TAajPnfpSTp+XdyPVBR7TlTsturUCpryP0ZX1S3VJk2IaneB123thtcOtWsbqdT3Bb846H7yudI95WVTixIS/KIwoCbekSf8Y9+iW/xRVSWLRVc1gpigDxXfieSA7bI+qiUBjiKR7QU1KFYZA58VcOQhzeMLY6an34rsW4WHAwzzSv8Q6vrwpn8Ct9fTsIeiZsWZLueNkIUfjR0G1bHHoT2RHKton0AMRjOUGSKUUB4DNZ5xzXvC0jvUMWlgHB9z2wBCsIkIDVWqSA2DD0xeIY2wSUVPwPc1MnBAf/Fx3poweUlcPWglR2VaO9ematC4hfLxxkGldGQt3C6ZLPsm96S7o6j88rwOqkDNIR1pNJOepgciJH/w4Xwtg9gJ52CpdlCeSllRQD74l95ysmZ2D/gLweNoUt61P0RYQQelio8VnPUNB1e2uK7zW9joG1k59CjJGQNvuZr6JkQ9+Hxo5xKEOy9KcpT6t48wTzbz3YMFDxTNl0/DzL8qdTU2UrSW6/TFgPLokbAQN00yhw0lg8cR/e1m+ujFyBeesL3luwE6HNcIyK5Y/+To04vR3OD7Uz8cnABxWyOeSBm2R2bu2fxeN0Hlv+qhoOYtbZ1DKx/aES4z51jATynEIdMIMSNhmVDoDiGODh9ocenzg/DUarjIzWltPFRyQj+tnFGTXp7C87s3yAf248ZB0HHhK1GCppxB4hsv89nNtWH1JdWjsc243s3f0WOZtJ1f+9yeybViJCW47ez7HkwtTq2AVeg+lHrb4TPCL5pBKwUOj5GVe2DzMFBtjilcl/ED4gev7DK383iyB4tGVZa1ALPKUyiyKV3sCRV/mN5DSGeASafI6OOjjUKifYCJaxOHFQGr6zvfhVj9L2Cl/hthxplTWoLpo4I7+oLPQJIrOMPf8FHLtRLAYthsxT3K02mVtUMhrviaVh5/kJKMMd4iRc8YXloC0r8roivoEPr5SzDprSffh8a2N2KRAHd3yrp4z7RxlpWKPWr5whD56q279S70A9r/r5r0bVzwabhKkTSJxc2LN72QondANsGFDYPD3Rm+FwSO2JwwgIG8GQxBbMWPOEqD0qDmaebNfP/EpbeF8mvA8v4e58CIv1LaHZuEky6vc16woEYHm11UuH6ChHbWxCoDXJsVM/jPme1vPlic38i9XYsE2c199gP1ikBGQANlryeIWH8wXtPUXNflNecMqIQkWAWSK/8jujgtylBQ/CklRyeW0+vyxV5eo8S8TfnonyG2eiHN1VS3HGLSidcYRi54IsOMtuR773QoLPZeRXlsNWO5kc3xcHU7K6olsMNtQhaFnkf3GATh9H80GUvEMK9u5yMUrCoYWuUy7JQhjsl+B1QbAFftdDu8ESgTOIKmFOLg+F9CH4lJrCqnwUdCs93zbJem2++Y64HRFLSUXwlhEUuQVugX7BejmcMYWMjYXROlatnznqYXcWW2uxx6ZNxQv0eB/CN1i4q1G8y9XUh4wz/caY8ly+eaTU5J4wGHfnUDpssu+TUvE5PGUs1gW6FswHlf1IXEnvKDIXKajbJgYnjEekVG8FxcSUc/10Mw/vqk/GQqdMOguf3mShlUIbtX2JVrA5ClZ9qza4HEXC7RkmxJLyc5dDyX/CuFdoDzrVu+1+JqRsFHGeLCo9rNvIQjvG09GQX6uDUavi25hCcOgug2DI0PuVLjcESFDyaYNdKo9GsiCEBpLPglp9viA2vX2kG6P2pidgsGfcBgdGuYGQbd23Qu9QpOd8AAuyWsm0dX6hKO2ChoAPVQxDNcj9N6UjumggVQ6zOuC0+gOcao/aPs/eH9agchdtnWKuL1clo4FduP4sdDtTvnJLFYnXONM//LSnjqSyBc7rzjJ2cxzPWQtLFawErzHXukl2eeP/xpDvLU0G6JroeJqBitHIoK00FGdxTUnrJBgy1DnBoIgUhxOvb1wtnx/O4DDS5tJZBDbl9XVbRmSfcljfQ5mB38hQ51CuYodHE9q12Bk1FtSwbVKvPHGb+9EdkbktJKRgdJubAQ+ajOCyMjEDCp9xLeKnlFL+WesI0Ro+rnmQL0qXVzkhZj8LP4a8yFYieIXCApLveflfv2yRJf3a/EML7yIgoEuzejddFrcbupWxDRqwS1YcLDkvGBEzjp8zuVnr72GfaFW/nvU9V9P/Z0fFS5hZhG5MnEp0Qzjsy/eKRI=","purposes":["sign"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"editor","scheme":"ml-dsa-65"},{"did":"did:key:z6MkiHaTrUvYfXFtTw39oiWrgan52dRBHYgm9WeoiEPwMotg","id":"wit","person":{"name":"Open Witness (fictional)"},"public":"OPPD6UEKZ7IObfmh/pzKS29cNjnz9WbKMQivMBXrlC0=","purposes":["witness"],"registered_at":"2026-09-01T00:00:00Z","revoked_at":null,"role":"guest","scheme":"ed25519"}],"store":"smithlab"} diff --git a/fixtures/records/snapshot.json b/fixtures/records/snapshot.json new file mode 100644 index 0000000..6391306 --- /dev/null +++ b/fixtures/records/snapshot.json @@ -0,0 +1 @@ +{"claims":[{"level":"illustrative","pin":"illustrative-pin","ref":"amber/k-bond","typst":"K_r"}],"datasets":[{"hash":"8e62106c032120c2c2c7b560646983937db2624a6cf768df0be7125c7c29f33f","id":"ds-hale-ctct-scan"}],"format":"scienting-snapshot/1","made_at":"2026-10-11T21:00:00Z","quotes":[{"address":"smithlab/hale2026harmonic-damb#a4jrz2t@f64c6a","anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"a4jrz2t","node_hash":"f64c6a5040f9c773d5ac4e559b58465aeae30bba79a82fc38b14ac7b61826ba8","own_hash":"dde95db22e0600c8e6da72dd6701436315a786655cb74fc313a4bf574c9356ee","quote":{"exact":"Table 1 lists the fitted constants for both parameter sets."},"rev":12,"store":"smithlab"},"fidelity":"F3","result":"current","text":"Table 1 lists the fitted constants for both parameter sets."}],"store":"smithlab"} diff --git a/fixtures/records/submissions/anchor-hit.json b/fixtures/records/submissions/anchor-hit.json new file mode 100644 index 0000000..538560b --- /dev/null +++ b/fixtures/records/submissions/anchor-hit.json @@ -0,0 +1 @@ +{"answers":{"anchors":[{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","quote":{"exact":"310.0"},"rev":12,"store":"smithlab"}]},"doc":"smithlab/hale2026harmonic-damb","exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-submission/1","id":"kpjevbt3j6s3w","rev":12,"student":"s-7k2m","submitted_at":"2026-10-20T10:00:00Z"} diff --git a/fixtures/records/submissions/anchor-miss.json b/fixtures/records/submissions/anchor-miss.json new file mode 100644 index 0000000..d2744c9 --- /dev/null +++ b/fixtures/records/submissions/anchor-miss.json @@ -0,0 +1 @@ +{"answers":{"anchors":[{"context":{"column_path":["Set B","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"j6y45v6","node_hash":"00c4b92e220303ebc2bfb36aa557ac80ae4dba1675e9ed47adb82f6aeff10634","own_hash":"111d2b2cb30e3b04aff04b7de13a105a07a189d5ba97ae7d78eb7601ac99f9d9","quote":{"exact":"305.2"},"rev":12,"store":"smithlab"}]},"doc":"smithlab/hale2026harmonic-damb","exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-submission/1","id":"ysw9hjztre498","rev":12,"student":"s-9q4p","submitted_at":"2026-10-20T10:00:00Z"} diff --git a/fixtures/records/submissions/check-overlap.json b/fixtures/records/submissions/check-overlap.json new file mode 100644 index 0000000..6c5ed9f --- /dev/null +++ b/fixtures/records/submissions/check-overlap.json @@ -0,0 +1 @@ +{"answers":{"anchors":[{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"kea5026","node_hash":"b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33","own_hash":"d673d236c03d9583ecf6e01fa819765ec324dc684bd9bbc6967fa50f216e34d2","quote":{"exact":"most common description of covalent","prefix":"Harmonic bond terms remain the ","suffix":" stretching in classical force f"},"rev":12,"span":[31,66],"store":"smithlab"}],"verdict":"supports"},"doc":"smithlab/hale2026harmonic-damb","exercise":"tag:scient.ing,2026:annotation:smithlab/y7bd3he0jwjbx","format":"scienting-submission/1","id":"n7me2fmcw8ree","rev":12,"student":"s-7k2m","submitted_at":"2026-10-20T10:05:00Z"} diff --git a/fixtures/records/suspect.json b/fixtures/records/suspect.json new file mode 100644 index 0000000..71ee861 --- /dev/null +++ b/fixtures/records/suspect.json @@ -0,0 +1 @@ +{"a":"10-3","b":"10−3","crop":"321a926653b9e097987d255d9286880893d71abf895d73f1649403ed9ac0877d","format":"scienting-suspect/1","id":"tncskbdzr6r5r","kind":"number","node":"ec5jc93","note":"The text layer reads a hyphen on the line; the page image shows a raised minus three."} diff --git a/fixtures/records/view.vl.json b/fixtures/records/view.vl.json new file mode 100644 index 0000000..cece449 --- /dev/null +++ b/fixtures/records/view.vl.json @@ -0,0 +1 @@ +{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"name":"ds-hale-ctct-scan"},"encoding":{"x":{"field":"r","title":"r (Å)","type":"quantitative"},"y":{"field":"e","title":"E (kcal/mol)","type":"quantitative"}},"mark":{"type":"point"},"usermeta":{"scienting":{"data":[{"dataset":"ds-hale-ctct-scan","hash":"8e62106c032120c2c2c7b560646983937db2624a6cf768df0be7125c7c29f33f","name":"ds-hale-ctct-scan","resource":"scan"}],"format":"scienting-view/1","id":"ctct-scan"}}} diff --git a/fixtures/src/README.md b/fixtures/src/README.md new file mode 100644 index 0000000..69fe7e8 --- /dev/null +++ b/fixtures/src/README.md @@ -0,0 +1,20 @@ +# Fixture sources + +Each source describes a document as a converter first read it, mistakes included, in a shorthand that `tools/build.py` expands. +The build mints IDs, applies the listed corrections, lays out synthetic geometry, signs the listed receipts and writes the package. +The shorthand is tooling, not a format. + +| Shorthand | Becomes | +| --- | --- | +| `{"p": [...]}` | A paragraph of the listed sentences. | +| `{"s": [...]}` | A sentence; a string part is a text run. | +| `{"sup": t}`, `{"sub": t}`, `{"em": t}` | A styled text run. | +| `{"m": src}`, `{"t": src}` | A TeX or Typst math run. | +| `{"cite": [...], "text": t}`, `{"xref": target, "text": t}`, `{"fn": name, "text": t}` | Citation, cross-reference and footnote-mark runs. | +| `{"eq": {...}}` | A display equation inside the sentence. | +| `{"row": [...]}`, `{"c": [...]}` | A table row, and a cell with `role`, `rowspan`, `colspan` and `col`. | +| `"name": "@x"` | A local name, replaced by the minted ID; `ext::@x` names a node of another source. | +| `"page": n` | The page the node and its descendants are laid out on. | + +`corrections` lists the operations in order, naming nodes by local name; `crop` names the node whose crop is the evidence. +`anchors_at_rev0` lists the anchors whose resolution `vectors/resolve.jsonl` records, and `receipts` the receipts, spot-checks and revocations to sign. diff --git a/fixtures/src/hale2026harmonic.json b/fixtures/src/hale2026harmonic.json new file mode 100644 index 0000000..230271e --- /dev/null +++ b/fixtures/src/hale2026harmonic.json @@ -0,0 +1,173 @@ +{ + "comment": "A synthetic chemistry paper, as first read, with the reading errors its corrections fix. Text written for this fixture; CC0-1.0.", + "document": { + "store": "smithlab", + "kind": "article", + "work": {"same_as": ["doi:10.5555/example.hale.2026"]}, + "version": {"type": "version-of-record", "date": "2026-03-02"}, + "relations": [], + "meta": {"type": "article-journal", "title": "Harmonic bond parameters for small organic molecules from a two-step fit", "author": [{"family": "Hale", "given": "R."}, {"family": "Osei", "given": "M."}], "container-title": "Journal of Example Chemistry", "volume": "14", "page": "101-109", "issued": {"date-parts": [[2026, 3, 2]]}, "DOI": "10.5555/example.hale.2026"}, + "language": "en", + "license": {"text": "All rights reserved by the publisher (fictional)."}, + "policy": "full" + }, + "legacy_aliases": {"b-p01-text-003": "@s3", "b-p02-table-001": "@tab1"}, + "tree": {"kind": "document", "children": [ + {"kind": "front", "page": 1, "children": [ + {"kind": "title", "children": [{"s": ["Harmonic bond parameters for small organic molecules from a two-step fit"], "fidelity": "F2"}]}, + {"kind": "authors", "runs": ["R. Hale and M. Osei"], "fidelity": "F2"}, + {"kind": "abstract", "children": [{"p": [ + {"s": ["We fit harmonic bond constants for twelve bonds in two steps, first to a scan and then to vibrational frequencies."], "fidelity": "F2"}, + {"s": ["The two parameter sets agree to within 2% for every bond."], "fidelity": "F2"} + ]}]} + ]}, + {"kind": "section", "name": "@sec1", "label": "1", "level": 1, "page": 1, "title": "Introduction", "children": [ + {"p": [ + {"name": "@s1", "s": ["Harmonic bond terms remain the most common description of covalent stretching in classical force fields.", {"cite": ["@r1"], "text": "1"}], "fidelity": "F2"}, + {"name": "@s2", "s": ["The bond energy is given by ", {"eq": {"name": "@eq1", "label": "(l)", "tex": "E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2", "fidelity": "F1"}}, " where ", {"m": "K_r"}, " is the bond force constant and ", {"m": "r_\\mathrm{eq}"}, " the equilibrium bond length."], "fidelity": "F2"}, + {"name": "@s3", "s": ["Water, H", {"m": "_2"}, "O, served as the first test case, with a bending band near 1595 cm⁻¹.", {"cite": ["@r2"], "text": "2"}], "fidelity": "F2"} + ]}, + {"p": [ + {"name": "@s4", "s": ["Values below 10-3 kcal mol⁻¹ were treated as zero. ", {"xref": "@tab1", "text": "Table 1"}, " lists the fitted constants for both parameter sets."], "fidelity": "F0"} + ]} + ]}, + {"kind": "section", "name": "@sec2", "label": "2", "level": 1, "page": 2, "title": "Methods", "children": [ + {"name": "@para6", "p": [ + {"name": "@s6a", "s": ["Each bond was scanned in steps of 0.01 Å around its minimum, and the energies were"], "fidelity": "F0"}, + {"name": "@s6b", "s": ["fitted by least squares."], "fidelity": "F0"} + ]}, + {"name": "@para7", "p": [ + {"name": "@s7", "s": [{"xref": "@fig1", "text": "Figure 1"}, " shows the scan for the C–C bond of ethane.", {"fn": "@fn1", "text": "a"}], "fidelity": "F2"} + ]}, + {"name": "@head2", "p": [{"name": "@rh", "s": ["J. Example Chem. 2026, 14, 101–109"], "fidelity": "F0"}]}, + {"kind": "footnote", "name": "@fn1", "label": "a", "children": [{"name": "@fns", "s": ["Scans held every other coordinate fixed."], "fidelity": "F2"}]}, + {"kind": "figure", "name": "@fig1", "label": "Figure l", "children": [ + {"kind": "panel", "name": "@pa", "label": "a", "figure_text": [ + {"text": "r (Å)", "role": "axis-label", "name": "@ft_x"}, + {"text": "E (kcal mol⁻¹)", "role": "axis-label", "name": "@ft_y"}, + {"text": "1.4", "role": "tick-label"}, {"text": "1.5", "role": "tick-label"}, {"text": "1.6", "role": "tick-label"} + ]}, + {"kind": "panel", "name": "@pb", "label": "b"}, + {"kind": "caption", "children": [ + {"name": "@cap1", "s": ["Bond energy along the C–C stretch of ethane."], "fidelity": "F2"}, + {"name": "@cap2", "s": ["(a) The scan."], "fidelity": "F2"}, + {"name": "@cap3", "s": ["(b) The residual of the fit."], "fidelity": "F2"} + ]} + ]}, + {"kind": "table", "name": "@tab1", "label": "Table 1", + "columns": [ + {"name": "@col_bond", "header_path": ["@h_bond"]}, + {"name": "@col_ak", "header_path": ["@h_a", "@h_ak"]}, + {"name": "@col_ar", "header_path": ["@h_a", "@h_ar"]}, + {"name": "@col_bk", "header_path": ["@h_b", "@h_bk"]}, + {"name": "@col_br", "header_path": ["@h_b", "@h_br"]} + ], + "children": [ + {"kind": "caption", "children": [{"s": ["Fitted harmonic bond parameters."], "fidelity": "F2"}]}, + {"kind": "table-head", "children": [ + {"row": [ + {"name": "@h_bond", "c": ["Bond"], "role": "column-header", "rowspan": 2, "col": "@col_bond"}, + {"name": "@h_a", "c": ["Set A"], "role": "column-header", "colspan": 2, "col": "@col_ak"}, + {"name": "@h_b", "c": ["Set B"], "role": "column-header", "colspan": 1, "col": "@col_bk"} + ]}, + {"row": [ + {"name": "@h_ak", "c": [{"m": "K_r"}, " (kcal mol⁻¹ Å⁻²)"], "role": "column-header", "col": "@col_ak"}, + {"name": "@h_ar", "c": [{"m": "r_\\mathrm{eq}"}, " (Å)"], "role": "column-header", "col": "@col_ar"}, + {"name": "@h_bk", "c": [{"m": "K_r"}, " (kcal mol⁻¹ Å⁻²)"], "role": "column-header", "col": "@col_bk"}, + {"name": "@h_br", "c": [{"m": "r_\\mathrm{eq}"}, " (Å)"], "role": "column-header", "col": "@col_br"} + ]} + ]}, + {"kind": "table-body", "name": "@body", "children": [ + {"row": [{"name": "@grp", "c": ["Bond parameters"], "role": "row-group-header", "colspan": 5, "col": "@col_bond"}]}, + {"name": "@row_cc", "header_path": ["@grp", "@cc"], "row": [ + {"name": "@cc", "c": ["CT–CT"], "role": "row-header", "col": "@col_bond"}, + {"name": "@cc_ak", "c": ["3l0.0"], "col": "@col_ak", "fidelity": "F0"}, + {"name": "@cc_ar", "c": ["1.526"], "col": "@col_ar"}, + {"name": "@cc_bk", "c": ["305.2"], "col": "@col_bk"}, + {"name": "@cc_br", "c": ["1.5260"], "col": "@col_br"} + ]}, + {"name": "@row_ch", "header_path": ["@grp", "@ch"], "row": [ + {"name": "@ch", "c": ["CT–HC"], "role": "row-header", "col": "@col_bond"}, + {"name": "@ch_ak", "c": ["340.0"], "col": "@col_ak"}, + {"name": "@ch_ar", "c": ["1.090"], "col": "@col_ar"}, + {"name": "@ch_bk", "c": ["338.7 1.0900"], "col": "@col_bk", "fidelity": "F0"} + ]} + ]}, + {"kind": "table-note", "children": [{"s": ["Set B was refitted with half the step size."], "fidelity": "F2"}]} + ]} + ]}, + {"kind": "back", "page": 2, "children": [ + {"kind": "references", "children": [ + {"kind": "reference", "name": "@r1", "label": "1", "runs": ["(1) A. Author and B. Author, J. Example Chem. 2001, 12, 345–350."], "fidelity": "F2", + "csl": {"type": "article-journal", "author": [{"family": "Author", "given": "A."}, {"family": "Author", "given": "B."}], "container-title": "J. Example Chem.", "volume": "12", "page": "345-350", "issued": {"date-parts": [[2001]]}, "DOI": "10.5555/example.ref1"}, + "resolution": {"type": "doi", "doi": "10.5555/example.ref1"}}, + {"kind": "reference", "name": "@r2", "label": "2", "runs": ["(2) C. Writer, Example Spectroscopy 2010, 7, 89–97."], "fidelity": "F2", + "csl": {"type": "article-journal", "author": [{"family": "Writer", "given": "C."}], "container-title": "Example Spectroscopy", "volume": "7", "page": "89-97", "issued": {"date-parts": [[2010]]}}, + "resolution": {"type": "none"}} + ]} + ]} + ]}, + "corrections": [ + {"op": "replace", "target": "@cc_ak", "find": "3l0.0", "replace": "310.0", "crop": "@cc_ak", "reason": "OCR read the digit 1 as the letter l.", "at": "2026-10-02T10:00:00Z"}, + {"op": "replace", "target": "@s4", "find": "10-3", "replace": [{"kind": "text", "text": "10"}, {"kind": "text", "text": "−3", "style": ["sup"]}], "crop": "@s4", "reason": "The reading lost the superscript.", "at": "2026-10-02T10:01:00Z"}, + {"op": "split", "target": "@s4", "before": "Table 1", "new_name": "@s5", "reason": "A missed sentence boundary.", "at": "2026-10-02T10:02:00Z"}, + {"op": "merge", "target": "@s6a", "with": "@s6b", "joiner": " ", "reason": "A false boundary at a line break.", "at": "2026-10-02T10:03:00Z"}, + {"op": "merge", "target": "@para6", "with": "@para7", "reason": "A paragraph split at a column break.", "at": "2026-10-02T10:03:30Z"}, + {"op": "delete", "target": "@head2", "crop": "@rh", "reason": "A running head read as text.", "at": "2026-10-02T10:04:00Z"}, + {"op": "relabel", "target": "@eq1", "label": "(1)", "crop": "@eq1", "reason": "OCR read the equation number 1 as the letter l.", "at": "2026-10-02T10:05:00Z"}, + {"op": "delete", "target": "@row_ch", "crop": "@ch", "reason": "Two cells were read as one; the row is replaced.", "at": "2026-10-02T10:06:00Z"}, + {"op": "insert", "parent": "@body", "place_after": "@row_cc", "crop": "@body", "reason": "The CT–HC row, read again from the page.", "at": "2026-10-02T10:07:00Z", + "node": {"name": "@row_ch2", "header_path": ["@grp", "@ch2"], "row": [ + {"name": "@ch2", "c": ["CT–HC"], "role": "row-header", "col": "@col_bond"}, + {"name": "@ch2_ak", "c": ["340.0"], "col": "@col_ak"}, + {"name": "@ch2_ar", "c": ["1.090"], "col": "@col_ar"}, + {"name": "@ch2_bk", "c": ["338.7"], "col": "@col_bk"}, + {"name": "@ch2_br", "c": ["1.0900"], "col": "@col_br"}]}}, + {"op": "insert", "parent": "@body", "place_after": "@row_ch2", "crop": "@body", "reason": "The reading dropped the OW–HW row.", "at": "2026-10-02T10:08:00Z", + "node": {"name": "@row_ow", "header_path": ["@grp", "@ow"], "row": [ + {"name": "@ow", "c": ["OW–HW"], "role": "row-header", "col": "@col_bond"}, + {"name": "@ow_ak", "c": ["553.0"], "col": "@col_ak"}, + {"name": "@ow_ar", "c": ["0.9572"], "col": "@col_ar"}, + {"name": "@ow_bk", "c": ["548.1"], "col": "@col_bk"}, + {"name": "@ow_br", "c": ["0.9570"], "col": "@col_br"}]}}, + {"op": "set", "target": "@h_b", "attr": "colspan", "value": 2, "crop": "@h_b", "reason": "Set B spans two columns.", "at": "2026-10-02T10:09:00Z"}, + {"op": "relabel", "target": "@fig1", "label": "Figure 1", "crop": "@fig1", "reason": "OCR read the figure number 1 as the letter l.", "at": "2026-10-02T10:10:00Z"} + ], + "anchors_at_rev0": { + "span-current": {"node": "@s3", "quote": "H$_2$O"}, + "leaf-stale": {"node": "@cc_ak"}, + "leaf-current": {"node": "@cc_br"}, + "body-drift-high": {"node": "@body"}, + "table-changed-below": {"node": "@tab1"}, + "section-changed-below": {"node": "@sec2"}, + "span-reattached": {"node": "@s4", "quote": "treated as zero"}, + "span-stale-after-split": {"node": "@s4", "quote": "fitted constants"}, + "span-moved-by-merge": {"node": "@s6b", "quote": "least squares"}, + "leaf-deleted": {"node": "@rh"}, + "equation-reattached": {"node": "@eq1"}, + "figure-relabel": {"node": "@fig1"}, + "cell-header-paths": {"node": "@ch_ar"}, + "via-alias": {"alias": "b-p01-text-003", "node": "@s3", "quote": "first test case"}, + "paragraph-changed-below": {"node": "@para6"}, + "row-drift-low": {"node": "@row_cc"}, + "paragraph-moved": {"node": "@para7"} + }, + "receipts": [ + {"name": "r0", "by": "ana", "level": "F3", "scope": "targeted:lode", "at": "2026-10-01T16:00:00Z", "rev": 0, "nodes": ["@cc_ak", "@cc_br", "@cc_ar"], "crops": true}, + {"name": "r1", "by": "ana", "level": "F3", "scope": "targeted:lode", "at": "2026-10-11T15:02:11Z", "nodes": ["@cc", "@cc_ak", "@cc_ar", "@cc_bk", "@cc_br", "@ch2", "@ch2_ak", "@ch2_ar", "@ch2_bk", "@ch2_br", "@ow", "@ow_ak", "@ow_ar", "@ow_bk", "@ow_br", "@h_ak", "@h_ar", "@h_bk", "@h_br", "@s2", "@eq1", "@s3", "@s4"], "crops": true}, + {"name": "q1", "qa_of": "r1", "by": "ben", "key": "ben-spot", "at": "2026-10-12T09:00:00Z", "errors": []}, + {"name": "r2", "by": "ana", "level": "F3", "scope": "section:@sec1", "at": "2026-10-11T16:30:00Z", "nodes": ["@s1", "@s5"], "crops": true}, + {"name": "r3", "by": "cara", "level": "F3", "scope": "page:2", "at": "2026-10-11T17:00:00Z", "nodes": ["@s6a", "@s7", "@fns"], "crops": true}, + {"name": "v1", "revoke": "r3", "by": "cara", "at": "2026-10-11T17:20:00Z", "reason": "Signed against the crops of another paper."}, + {"name": "r4", "by": "ana", "level": "F3", "scope": "targeted:captions", "at": "2026-10-11T18:00:00Z", "nodes": ["@cap1", "@cap2", "@cap3"], "crops": true}, + {"name": "q2", "qa_of": "r4", "by": "ben", "key": "ben-spot", "at": "2026-10-12T09:30:00Z", "errors": [{"node": "@cap2", "kind": "word", "note": "The page prints a period the reading lacks."}]} + ], + "pages": { + "witness": {"sha_seed": "hale2026harmonic: publisher PDF, download 1 (synthetic)", "size": 482113}, + "size": [612, 792], + "labels": ["101", "102"], + "stamp": "Downloaded via UNIVERSITY OF EXAMPLE on October 11, 2026 at 15:02:11 (UTC).", + "stamp2": "See https://pubs.acs.org/sharingguidelines for options on how to legitimately share published articles.", + "running_head": {"2": "J. Example Chem. 2026, 14, 101–109"} + } +} diff --git a/fixtures/src/okafor2025open.json b/fixtures/src/okafor2025open.json new file mode 100644 index 0000000..692ebab --- /dev/null +++ b/fixtures/src/okafor2025open.json @@ -0,0 +1,39 @@ +{ + "comment": "A synthetic open-access paper with a JATS witness and a PDF witness. Text written for this fixture; CC0-1.0. The license fields describe the fictional work.", + "document": { + "kind": "article", + "work": {"same_as": ["doi:10.5555/example.okafor.2025"]}, + "version": {"type": "version-of-record", "date": "2025-11-20"}, + "relations": [], + "meta": {"type": "article-journal", "title": "Solvent shifts of a model carbonyl stretch", "author": [{"family": "Okafor", "given": "N."}, {"family": "Lindqvist", "given": "E."}], "container-title": "Open Example Letters", "volume": "3", "page": "e17", "issued": {"date-parts": [[2025, 11, 20]]}, "DOI": "10.5555/example.okafor.2025"}, + "language": "en", + "license": {"spdx": "CC-BY-4.0", "url": "https://creativecommons.org/licenses/by/4.0/"}, + "policy": "full" + }, + "tree": {"kind": "document", "children": [ + {"kind": "front", "page": 1, "children": [ + {"kind": "title", "children": [{"s": ["Solvent shifts of a model carbonyl stretch"], "fidelity": "F2"}]}, + {"kind": "authors", "runs": ["N. Okafor and E. Lindqvist"], "fidelity": "F2"} + ]}, + {"kind": "section", "label": "1", "level": 1, "page": 1, "title": "Results", "children": [ + {"p": [ + {"name": "@o1", "s": ["The carbonyl band of the model ketone moves from 1718 cm⁻¹ in hexane to 1702 cm⁻¹ in methanol.", {"cite": ["@or1"], "text": "1"}], "fidelity": "F2"}, + {"name": "@o2", "s": ["The shift scales with the solvent's hydrogen-bond donor strength, ", {"m": "\\alpha"}, ", with a slope of ", {"m": "-17 \\pm 2"}, " cm⁻¹."], "fidelity": "F2"}, + {"name": "@o3", "s": ["Two outliers, both fluorinated alcohols, fall below the line by about 4 cm⁻¹."], "fidelity": "F2"} + ]} + ]}, + {"kind": "back", "page": 1, "children": [ + {"kind": "references", "children": [ + {"kind": "reference", "name": "@or1", "label": "1", "runs": ["1. P. Example and Q. Example, Spectrochim. Example 2019, 30, 11–19."], "fidelity": "F2", + "csl": {"type": "article-journal", "author": [{"family": "Example", "given": "P."}, {"family": "Example", "given": "Q."}], "container-title": "Spectrochim. Example", "volume": "30", "page": "11-19", "issued": {"date-parts": [[2019]]}, "DOI": "10.5555/example.ref3"}, + "resolution": {"type": "doi", "doi": "10.5555/example.ref3"}} + ]} + ]} + ]}, + "pages": { + "witness": {"sha_seed": "okafor2025open: publisher PDF (synthetic)", "size": 201977}, + "jats": {"sha_seed": "okafor2025open: JATS XML from the repository (synthetic)", "size": 38211}, + "size": [595.28, 841.89], + "labels": ["e17-1"] + } +} diff --git a/fixtures/src/smithlab2027charges.json b/fixtures/src/smithlab2027charges.json new file mode 100644 index 0000000..56ad690 --- /dev/null +++ b/fixtures/src/smithlab2027charges.json @@ -0,0 +1,35 @@ +{ + "comment": "A short synthetic Typst draft that cites sentences of hale2026harmonic by address. Text written for this fixture; CC0-1.0.", + "document": { + "store": "smithlab", + "kind": "draft", + "work": {"same_as": []}, + "version": {"type": "draft", "seq": 3}, + "relations": [], + "meta": {"type": "report", "title": "Fixed charges in biomolecular force fields", "author": [{"family": "Writer", "given": "A."}], "issued": {"date-parts": [[2027]]}}, + "language": "en", + "license": {"spdx": "CC-BY-4.0"}, + "policy": "full" + }, + "tree": {"kind": "document", "children": [ + {"kind": "front", "children": [ + {"kind": "title", "children": [{"s": ["Fixed charges in biomolecular force fields"], "fidelity": "F2"}]}, + {"kind": "authors", "runs": ["A. Writer"], "fidelity": "F2"} + ]}, + {"kind": "section", "label": "1", "level": 1, "title": "Introduction", "children": [ + {"p": [ + {"name": "@d1", "s": ["The bond term is harmonic in the bond length."], "fidelity": "F2"}, + {"name": "@d2", "s": ["Its constants come from a two-step fit ", {"xref": "ext:hale2026harmonic:@s5", "text": "(Hale and Osei, Table 1)"}, ".", {"cite": ["@dr1"], "text": "1"}], "fidelity": "F2"}, + {"name": "@d3", "s": ["In that fit the energy is ", {"t": "E = K_r (r - r_\"eq\")^2"}, ", up to a constant factor."], "fidelity": "F2"} + ]} + ]}, + {"kind": "back", "children": [ + {"kind": "references", "children": [ + {"kind": "reference", "name": "@dr1", "label": "1", "runs": ["1. R. Hale and M. Osei, J. Example Chem. 2026, 14, 101–109."], "fidelity": "F2", + "csl": {"type": "article-journal", "author": [{"family": "Hale", "given": "R."}, {"family": "Osei", "given": "M."}], "container-title": "J. Example Chem.", "volume": "14", "page": "101-109", "issued": {"date-parts": [[2026]]}, "DOI": "10.5555/example.hale.2026"}, + "resolution": {"type": "document", "doc": "ext:hale2026harmonic"}} + ]} + ]} + ]}, + "typst": {"sha_seed": "smithlab2027charges: Typst project, revision 3 (synthetic)", "size": 4211} +} diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..d062685 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,2093 @@ +version: 7 +platforms: +- name: linux-64 + virtual-packages: + - __unix=0=0 + - __linux=4.18 + - __glibc=2.28 + - __archspec=0=x86_64 +- name: linux-aarch64 + virtual-packages: + - __unix=0=0 + - __linux=4.18 + - __glibc=2.28 + - __archspec=0=aarch64 +- name: osx-64 + virtual-packages: + - __unix=0=0 + - __osx=13.0 + - __archspec=0=x86_64 +- name: osx-arm64 + virtual-packages: + - __unix=0=0 + - __osx=13.0 + - __archspec=0=m1 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.1.1-py314h8d76f0c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-50.0.2-py311hc91d8b8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260526.0-cxx17_h0dc7533_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-h39a168f_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-ha411449_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-h018ffa1_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.54.0-h13e7031_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-26.10.0-ha5cdc1e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.9.1-py314h7e8cd81_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.8-py314hd8ed1ab_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdownlint-cli2-0.23.3-h5ac6406_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.11-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.8-h4df99d1_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.8-h29ee22c_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.1.1-py314h65cb5ac_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-50.0.2-py311h9269228_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20260526.0-cxx17_hc5e897d_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.2.0-h384ecca_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.2.0-h011f0d3_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.2.0-hb247b97_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h80f16a2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.5-h4154aff_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.7.0-hdaad0be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.68.1-ha4b982d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpython-3.14.8-hc71fabe_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.54.0-h399dd60_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.4-hd6fdeab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.52.1-h80f16a2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-h2b6f883_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-26.10.0-hfa2f511_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.5-he6ad1d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.8-hbec3b18_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-ha7194a6_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-2026.9.1-py314h231d840_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_hf03c496_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.8-py314hd8ed1ab_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdownlint-cli2-0.23.3-h5ac6406_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.11-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.8-h4df99d1_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.8-py314hd8ed1ab_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdownlint-cli2-0.23.3-h5ac6406_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.11-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.8-h4df99d1_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.1.1-py314h0656537_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-50.0.2-py311hc027f23_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260526.0-cxx17_h6e8c311_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-he0616a4_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h4a2f56c_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h3d41943_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.54.0-h59ff3a2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-26.10.0-hb4a83e6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-2026.9.1-py314h3cfb53e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.8-py314hd8ed1ab_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdownlint-cli2-0.23.3-h5ac6406_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.11-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.8-h4df99d1_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.1.1-py314h618e29d_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-50.0.2-py311hc28ac56_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260526.0-cxx17_h4c27e2a_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-h1dcdb26_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-h5295a6a_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-h2ddc9cb_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.54.0-hca69786_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-26.10.0-h8d74fab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.9.1-py314hc05cd11_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 28948 + timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + sha256: 1a0d382c515ebf55f8ee1f38c8b81bc95af5c2acc42ad53b66bc5df932032f96 + md5: e675fabcf81499adc7edf58124fb1e01 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 257808 + timestamp: 1785906269155 +- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + sha256: 9c37cc233238adf366ea75b0e845662a5be07ceadf62e458183516369340274b + md5: 3ad2b403be8fc5612b9159e2ce621f69 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: + weak: + - c-ares >=1.34.8,<2.0a0 + size: 228700 + timestamp: 1787169971173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.1.1-py314h8d76f0c_3.conda + sha256: 15e38176fa2173e063a19dad3d55746ac4c757b028813380d7f22c42781af4c4 + md5: ee66d46f7693fdcbaa1761fb8a4f6c3d + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 307262 + timestamp: 1788485305536 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-50.0.2-py311hc91d8b8_0.conda + noarch: python + sha256: d1956b37648b45d54e884d765223974fe6e26d4e7ea248cd08c625ba8cd823ab + md5: e9af843b1d7656fd6bdbe9aa69e95579 + depends: + - python + - cffi >=2.0 + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - _python_abi3_support 1.* + - cpython >=3.11 + - openssl >=3.5.8,<4.0a0 + constrains: + - __glibc >=2.17 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + run_exports: {} + size: 1830947 + timestamp: 1790790516832 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + sha256: 9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae432 + md5: 72a381cbad04f24b1c2a43ef707f45b4 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14459115 + timestamp: 1786545741408 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_103.conda + sha256: 901649b1edbe841fd4ee7e2d491a05184ed540eb01cdae506872f344babc1d28 + md5: 2362c70e7e79827c32db35547d9c179b + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.46.1 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 742109 + timestamp: 1791565468810 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260526.0-cxx17_h0dc7533_3.conda + sha256: 24708450d80f4d542fc357c941909446e0b6caffb8baca478a0da1f74820e688 + md5: d224f3a53f55029366c73161f15461fb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + constrains: + - abseil-cpp =20260526.0 + - libabseil-static =20260526.0=cxx17* + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - libabseil >=20260526.0,<20260527.0a0 + - libabseil =*=cxx17* + size: 1440678 + timestamp: 1791681043356 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-h39a168f_4.conda + sha256: c4e9854c585f3ee1785f651287ecdf8c28f30a2ea1b159a513005f8a0f6453a3 + md5: df210655e30a05e3b069c91b7aaddd2d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + size: 80561 + timestamp: 1788480364653 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-ha411449_4.conda + sha256: d5ed24da3e583a92227fe77280978b7933f07a39a2b60156c5ad95e5c76733fa + md5: 0cfd601eb03cca403dcc248844787486 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 h39a168f_4 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 34739 + timestamp: 1788480374261 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-h018ffa1_4.conda + sha256: b9f3cb510337655485c2e79ce5f7dd468991b19ad29723ffa1175a0aed1b69ae + md5: 4136f6e4ef4835cc7df39a707cbd511c + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 h39a168f_4 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 + size: 298134 + timestamp: 1788480383223 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + sha256: e4418f68d01a6307c4431b585c71b584f40189877364e542ee87deb777f5e85b + md5: 7bc31538d6e3fb349e897353969237ec + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: BSD-2-Clause OR GPL-2.0-or-later + license_family: GPL + run_exports: + weak: + - libev >=4.33,<4.34.0a0 + size: 43220 + timestamp: 1785917328200 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + sha256: 6de73033a7c5f712c9c5a54124e4581e025691029835e5bceaf10a333a7e7bc0 + md5: 72cfd2b95b0540247220b42f58a148d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 77893 + timestamp: 1790346247149 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + sha256: c8c7583ef063bc3c430f1d48298e5ad24f796a35c22ed5b14183325825a61106 + md5: 6525a0b06aa4fd390795f0740636a9dd + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 68004 + timestamp: 1787753412298 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + sha256: e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea + md5: 735629b400b70eeab21a2ba8f5b1c2ce + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==16.2.0=*_7 + - libgomp 16.2.0 he0feb66_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 1058444 + timestamp: 1790303109576 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + sha256: 92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758 + md5: d904c7ddd95e026254b4b80808ee9e12 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 640566 + timestamp: 1790303046034 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + sha256: 9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab + md5: 1390b7c5ac0b1d8e447bc5efa6d3c8c2 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 112995 + timestamp: 1786348617826 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + sha256: 46820b4a835e175940ae20bec00fdddaff804cda27a1408ab1b95e77a2196437 + md5: fcfed1dc5053eb1901b66e7b1fc32588 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 92759 + timestamp: 1786650399772 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + sha256: 11a2f54a6f391e25738bce0023e6ef499600147bbcf21c1fa69d2e251b03cc6a + md5: 75d211f04ac87506f1f43420712a69fe + depends: + - __glibc >=2.17,<3.0.a0 + - c-ares >=1.34.8,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=15 + - libstdcxx >=15 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 + size: 649974 + timestamp: 1787177490105 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + build_number: 101 + sha256: 3dc27daa3470f9b6f863942d99db623d79204ea478955ea73e97d3519cae2ab5 + md5: 5782a594549b816514ca434a42bbf11a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + license: Python-2.0 + run_exports: + weak: + - libpython >=3.14,<4.0a0 + size: 10544845 + timestamp: 1791333423324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.54.0-h13e7031_1.conda + sha256: 4823e42fe95fc318d7af6125dc6ef33bd60c1152054d41661413250dc0e84e6c + md5: bb145547395d3329f3a1d930de9848b2 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.54.0,<4.0a0 + size: 984364 + timestamp: 1791584378129 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + sha256: fa7018298629fc429971fffd6ecba3d27a7b02e4e890d6a93ea01ffebe8cb745 + md5: 9b6707e0caca917fa6ea9ee473f37a5d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 16.2.0 ha9f2e26_7 + constrains: + - libstdcxx-ng ==16.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 6615436 + timestamp: 1790303132935 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + sha256: f34b8d1de9a2bf62476d8608057d9b8a918d97444236dc53a47128f2fae79041 + md5: 54a948337e66706380ff24d6b5fde63f + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libuuid >=2.42.4,<3.0a0 + size: 34442 + timestamp: 1790121449161 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + sha256: 67761d0206f84140047a367eaf9befe03a7e157a29ee25aee0047b40801cc6b6 + md5: 01c4ed87826af55996768af6dbc936b4 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 420040 + timestamp: 1785914567661 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + sha256: eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc736 + md5: 0de0122d9570a8ab637c6b73db268389 + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 63713 + timestamp: 1785362952714 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + sha256: 5d46557214ed184381dafe835b7c94a474a1c3b307a08a250b1ea4779b44ffb3 + md5: ee6c0cd80a60961a1f48aa3e0b91f986 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: X11 AND BSD-3-Clause + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 911196 + timestamp: 1786355078102 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-26.10.0-ha5cdc1e_0.conda + sha256: ea1ae98c7352198d6d6a4027f4a60d2b634e05d5fd6f0b97e72fc6c16712b2c7 + md5: 46a3d9861f49b845fbd54897ff07fe4f + depends: + - libgcc >=15 + - __glibc >=2.28,<3.0.a0 + - libstdcxx >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libuv >=1.52.1,<2.0a0 + - openssl >=3.5.8,<4.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libabseil >=20260526.0,<20260527.0a0 + - libabseil * cxx17* + - icu >=78.3,<79.0a0 + - c-ares >=1.34.8,<2.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - nodejs >=26.10.0,<27.0a0 + size: 20474429 + timestamp: 1790238478566 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + sha256: 9c1533f1cf784f0e250919c0c9762d0b0e6bc727a79290ffb7cea1ceca1d038c + md5: 5a51a2ea653f120240b1a9bf76e0aae9 + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=15 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 3195299 + timestamp: 1791098052301 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + build_number: 101 + sha256: e22f6a79d290935b2c854d325e260f70f364c7cc7ec0bc8308ded4f2f1eef7e6 + md5: 5cb98b237dfc2c64a65e660d7b99cfa5 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 hdc7f604_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libuuid >=2.42.4,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 26633451 + timestamp: 1791333464567 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + sha256: 01b3fe073a66e321970d09e04b388708f8cbdca5cdfbfcb7c9eeb470ad10383d + md5: 69c01c781e7c8190bbdaf79e3848c5ca + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 348899 + timestamp: 1787033801506 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.9.1-py314h7e8cd81_0.conda + sha256: 831c47efcbbd77e60462a41ee610b553d38bb7b3830a17f09472836c6a7cc0d4 + md5: 2bf437da5f8d248f328f28efb27f297f + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + run_exports: {} + size: 302823 + timestamp: 1791202484532 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + build_number: 104 + sha256: a1a241d172c1ccab067ba245206dd048bc3c2d1b84504b53c9468e99adfc16a1 + md5: 676a2f9b1c4fcf57b70aa5c65f6c60d0 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - xorg-libx11 >=1.8.13,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3566806 + timestamp: 1787272857910 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + sha256: 47d682b9f6d6ec9eb1a6e6c3e75ea6273e899e78fb7fc59f81d39745009fbc60 + md5: aa459086047c0e5e27023ab19f8cb86a + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 601301 + timestamp: 1786599621503 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 + md5: 468fd3bb9e1f671d36c2cbc677e56f1d + depends: + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 28926 + timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda + sha256: 24eacc8a20fd7c4616566178562bef7f9344eb4a8700cfc3180fa75a6ff9d39f + md5: fd544ef1c672d645bf78e5819cbb8f91 + depends: + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 194694 + timestamp: 1785906301397 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.8-h29ee22c_2.conda + sha256: 3838d10a78c206a1a4ec7ff041880b4f9b8ecde3520c911daae9e06baeb8858e + md5: eb80eb38625b8552a099aa88f8ba5db7 + depends: + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - c-ares >=1.34.8,<2.0a0 + size: 241210 + timestamp: 1787169968125 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.1.1-py314h65cb5ac_3.conda + sha256: cc2a7c807182bd18e07a6e255c98dc8a8feec2310ad2e801d296adebb8f2d9ea + md5: 30b36a0c4239d65f98209664afb3485b + depends: + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 329121 + timestamp: 1788485263944 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cryptography-50.0.2-py311h9269228_0.conda + noarch: python + sha256: 3636b61361abb09454348da5c32e6e3bbe62248547cd4255ce471469d671883a + md5: 98a1febddc9e9d0fae8341302bde57a2 + depends: + - python + - cffi >=2.0 + - libgcc >=15 + - _python_abi3_support 1.* + - cpython >=3.11 + - openssl >=3.5.8,<4.0a0 + constrains: + - __glibc >=2.17 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + run_exports: {} + size: 1795185 + timestamp: 1790790512228 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda + sha256: 54d921defd947adb58a90e10203d3bfe6c1f209f5f1a1ad2c6a9f7617f2fb59e + md5: b35bbb1b957440ed742f35fb96eb7f1c + depends: + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14688525 + timestamp: 1786545779464 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_103.conda + sha256: 516808982ad26ebdc4a9d8f71ee86ea55d0bc95382b7bca80620e0ac220971f3 + md5: ca781d8b499c39ddfe10e55a0347d6d9 + depends: + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-aarch64 2.46.1 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 905349 + timestamp: 1791565559147 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20260526.0-cxx17_hc5e897d_3.conda + sha256: e59c284b0449ab46569966c6ecad5b22848da3b18bb9f441c3907100c0f9ce03 + md5: ba780b0128b191a9e0e468fc0d7ce237 + depends: + - libgcc >=14 + - libstdcxx >=14 + constrains: + - abseil-cpp =20260526.0 + - libabseil-static =20260526.0=cxx17* + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - libabseil >=20260526.0,<20260527.0a0 + - libabseil =*=cxx17* + size: 1464151 + timestamp: 1791681000693 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.2.0-h384ecca_4.conda + sha256: 0caa2f9a3c56f139fd574d9300ecc062de96b11b50699024dde0365262f5a02a + md5: 20d76286cd6c6541181ccf57a8dbd990 + depends: + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + size: 80434 + timestamp: 1788480285525 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.2.0-h011f0d3_4.conda + sha256: 4aee7fa5bbbdd446b2c94ddbec121337bb98e20c15c477aaacf2a50cd5337208 + md5: fcf455f3f376d5a881e4c38de3943c31 + depends: + - libbrotlicommon 1.2.0 h384ecca_4 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 33822 + timestamp: 1788480293314 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.2.0-hb247b97_4.conda + sha256: e75639e57bc119cee647a283b27bd87ddb518b4d23df7f26176f4af6d47d79cd + md5: 2b6839131a93ae1148a80aa436906365 + depends: + - libbrotlicommon 1.2.0 h384ecca_4 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 + size: 348272 + timestamp: 1788480299628 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h80f16a2_3.conda + sha256: 4475f79a020e9ff2a5a0308c48cb2970a25d55c3dd724a97ab28bfac3be6cd49 + md5: f679b30a53d410d0b5ae0cb8f5b7397e + depends: + - libgcc >=14 + license: BSD-2-Clause OR GPL-2.0-or-later + license_family: GPL + run_exports: + weak: + - libev >=4.33,<4.34.0a0 + size: 45746 + timestamp: 1785917328690 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.5-h4154aff_0.conda + sha256: d155b9ee74abac0865095a66ebb008be967937a6deea6e7666ba01ead4a155fc + md5: e5a973222327d9183c25eddfc3a80828 + depends: + - libgcc >=15 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 79463 + timestamp: 1790346233159 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.7.0-hdaad0be_1.conda + sha256: b1879d78b622c5f4817fd6d77fe7ae3ab7b501542e3c2f4ac77198c54c62c189 + md5: f9e5b3e446b526b34a7e25ecec08efd9 + depends: + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 63137 + timestamp: 1787753382033 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda + sha256: eae7a3449d5a3b5351c5427137c076cc3fc826645c7bfc42dc10772b783826f1 + md5: 489d5c9dc62265b3f6a57f9a106f1caf + depends: + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==16.2.0=*_7 + - libgomp 16.2.0 h8acb6b2_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 627793 + timestamp: 1790302345214 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda + sha256: 4406fd67c5beeb99b9372f9bf07aa3e40ca141e337eceebac3ff64aa72799494 + md5: 259ded79ac497cfbcf5434540e8b81b6 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 617342 + timestamp: 1790302273072 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda + sha256: f760669fd1cea27f689f411c0d5488e26ce50e382c9b63e4ad348f959850124a + md5: e0e6411a60d00186eec7c73f4118ab67 + depends: + - libgcc >=14 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 125578 + timestamp: 1786348561649 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_2.conda + sha256: 5d6621a2229777824386164b40c67ff804fe98dd4165354cf73ee73e282a2adf + md5: eaaaec4776cd8a7b987c4b1782220141 + depends: + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 113885 + timestamp: 1786650485380 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.68.1-ha4b982d_1.conda + sha256: 0c28d734512fa2c66a232b2f3968eae7124dbd6ad42c594c752f1d08dfb86195 + md5: ff4b2b7c169c438bf648fb14f369c3b9 + depends: + - c-ares >=1.34.8,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=15 + - libstdcxx >=15 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 + size: 734829 + timestamp: 1787177407983 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpython-3.14.8-hc71fabe_101_cp314.conda + build_number: 101 + sha256: 35e8c023bb17bcbc01e049165960813137f1aa5b6ccc3fc87a0d40e5e2af47a1 + md5: c37c66978dbbd6f35a3c15bb324f89d5 + depends: + - libgcc >=15 + - libstdcxx >=15 + license: Python-2.0 + run_exports: + weak: + - libpython >=3.14,<4.0a0 + size: 9708299 + timestamp: 1791333141031 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.54.0-h399dd60_1.conda + sha256: 8698cc6bcb3406d8bf06f674ce623ebb33a1f4c7a3adb56ced22efd34c96a928 + md5: 5c86b41aba07fab6aaeee5ac172bd30e + depends: + - icu >=78.3,<79.0a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.54.0,<4.0a0 + size: 981485 + timestamp: 1791584316700 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda + sha256: b241a3acfa9cdb1359112864a1241225533c92642de3000d52ae65ef5d3a9786 + md5: 6c823668e78160957d1b061ceec15c2c + depends: + - libgcc 16.2.0 h205dda4_7 + constrains: + - libstdcxx-ng ==16.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 6236630 + timestamp: 1790302364054 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.4-hd6fdeab_0.conda + sha256: 4d94770cc7c47eb4a0d7b92f16d7a450506d1a82406d63c987d6208ab2fb8a16 + md5: 9d63e86dc027166aaaeb0c99a0a90fd7 + depends: + - libgcc >=15 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libuuid >=2.42.4,<3.0a0 + size: 36296 + timestamp: 1790121454455 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.52.1-h80f16a2_1.conda + sha256: 52f4bc6e340bde53bfe38e45f6cb1080a2d5f8891da9a647087f7cc6a6edfc22 + md5: 8e2136432f02841b9d8b848045f66d7d + depends: + - libgcc >=14 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 457209 + timestamp: 1785914582944 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda + sha256: 76efa6cc9d7e6f5ee3bbca0939f64054af2bdfb3c3632531f8e633cf6c2ea41e + md5: bd534c2fbe56d8c2ea3b2d8f5e12bca8 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 70108 + timestamp: 1785276540870 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-h2b6f883_1.conda + sha256: d69a04914139627f0a6bfd19412d6c7f1e37edc896af84a6011e07e8bc1e69fa + md5: c3b4349171ca987ff33a1de61f7b3f96 + depends: + - libgcc >=14 + license: X11 AND BSD-3-Clause + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 955422 + timestamp: 1786355019431 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-26.10.0-hfa2f511_0.conda + sha256: 2e39cfb9a12b3d98005e8b1c67eca6a67ba7e0d3594e8025c77902e9c7ce0d65 + md5: 3902ad80e094107c75712f90217e476f + depends: + - libgcc >=15 + - __glibc >=2.28,<3.0.a0 + - libstdcxx >=15 + - libnghttp2 >=1.68.1,<2.0a0 + - c-ares >=1.34.8,<2.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libuv >=1.52.1,<2.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libabseil >=20260526.0,<20260527.0a0 + - libabseil * cxx17* + - openssl >=3.5.8,<4.0a0 + - icu >=78.3,<79.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - nodejs >=26.10.0,<27.0a0 + size: 27191312 + timestamp: 1790238844670 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.5-he6ad1d5_0.conda + sha256: 238136f1df197ecd89bafd728a34d0642176f3170423d13d8276746d675a9485 + md5: 92aec5ec417d2ce9ae109e6c5ad377ff + depends: + - ca-certificates + - libgcc >=15 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 3716078 + timestamp: 1791097887829 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.8-hbec3b18_101_cp314.conda + build_number: 101 + sha256: b88a76c72f76e7ad9c46068e3c9467a363425a709ae9d7cdf8c8a7b0f30220d4 + md5: 44b96aaef0939e064699c8b843182cab + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-aarch64 >=2.36.1 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 hc71fabe_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libuuid >=2.42.4,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 25603222 + timestamp: 1791333177032 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-ha7194a6_1.conda + sha256: 80167dcf73a96b6d0c1bb2298d7b8b9bc21b27cc5bf56979f9c548b49a4d1722 + md5: 5b399a7afa10098f2a6b02263181426e + depends: + - libgcc >=15 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 364344 + timestamp: 1787033761576 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-2026.9.1-py314h231d840_0.conda + sha256: 00e7cf5897d3e9b4f500f371a1addb2d31850296c232218f9c0386ca5a2b6c88 + md5: a455ff00559c2d980cb20b8013141015 + depends: + - python + - libgcc >=15 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + run_exports: {} + size: 297482 + timestamp: 1791202301155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_hf03c496_4.conda + build_number: 104 + sha256: a1aa0d0f0b3d539644ff992e6dd0facf950c79df58fc37590ce5be84ff5e3f22 + md5: ebaded4b4b74c2cc43a754ded4eed76f + depends: + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + constrains: + - xorg-libx11 >=1.8.13,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3664220 + timestamp: 1787272859143 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda + sha256: 427fd14bcb3b8659796fecc682716617409350fb5a98e5b7b47558a10d1a2fc7 + md5: d942e34ac3920ba83f8b2d0169570187 + depends: + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 615477 + timestamp: 1786599613561 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + sha256: 2a7204314663eeda5dec482a956f0e2eaf289bd5b9953eaaaad0e81aa64638f2 + md5: 3845f3d75991bae0fb90884662f4327c + depends: + - cpython + - python-gil + license: MIT + license_family: MIT + run_exports: {} + size: 8144 + timestamp: 1784221492234 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab + md5: c6b0543676ecb1fb2d7643941fe375f2 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 64927 + timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + sha256: 0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6 + md5: 0f51e2391ade309db462a55611263e9c + depends: + - __unix + license: ISC + run_exports: {} + size: 131780 + timestamp: 1784754889428 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.8-py314hd8ed1ab_102.conda + noarch: generic + sha256: bf062db3f461ebb91b77ab4cea6841049dbe9d13c513a9ca2a101fa8ddea76a2 + md5: 54ecbe8d03ac833af969b3543bf116ef + depends: + - python >=3.14,<3.15.0a0 + - python_abi * *_cp314 + license: Python-2.0 + run_exports: {} + size: 51745 + timestamp: 1791826571351 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.conda + sha256: 328756a4555941d57af4a5f553e5d8598e9f3b37db028f557e30f9f0b3086db6 + md5: 204b5ca91eba7738790ecc333facbbbe + depends: + - attrs >=22.2.0 + - jsonschema-specifications >=2023.3.6 + - python >=3.10 + - referencing >=0.28.4 + - rpds-py >=0.25.0 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 82084 + timestamp: 1787579299493 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 + md5: 439cd0f567d697b20a8f45cb70a1005a + depends: + - python >=3.10 + - referencing >=0.31.0 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 19236 + timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdownlint-cli2-0.23.3-h5ac6406_0.conda + sha256: 45b0913f97baa92310fe259a36e2d21ab7e18ea091ee2cc530774a7d357c4570 + md5: c65177cc0ce74738af6b25ceb78d2965 + depends: + - nodejs + license: MIT + license_family: MIT + run_exports: {} + size: 2246247 + timestamp: 1789995027396 +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.11-pyh5ded981_0.conda + sha256: 99af7c6061d7aa73cfcef615500ddf3e9f4a58c844646b7d7ce58147fb5758d7 + md5: 3cd164745122ab557cc30879390089e8 + depends: + - python >=3.11 + - python + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 58624 + timestamp: 1791592610066 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.8-h4df99d1_102.conda + sha256: 96b092a54bc4187149726b121febef3142d21f3c9e69387f6029ee5f4e57ff85 + md5: 556734568e49dfd7cab8c0341ca1e67b + depends: + - cpython 3.14.8.* + - python_abi * *_cp314 + license: Python-2.0 + run_exports: {} + size: 51714 + timestamp: 1791826718684 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + build_number: 9 + sha256: e7f8e965bbfb98e08feb2365cacdad8bb218fa5b5a0a2752f747287f425f213c + md5: 350d89b50d7de805abf2e63e29dee451 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 6791 + timestamp: 1788302824440 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 + md5: 870293df500ca7e18bedefa5838a22ab + depends: + - attrs >=22.2.0 + - python >=3.10 + - rpds-py >=0.7.0 + - typing_extensions >=4.4.0 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 51788 + timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + sha256: 2d888f90af0686044882c74193ec80a90ec1943145d94a7b1b048958acda1848 + md5: c70ad746c22219b9700931707482992c + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + run_exports: {} + size: 52631 + timestamp: 1783002732887 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + sha256: b928c30ddcb0e3f544c6eade8352737e6e610e263276b90232db6a578ef899d8 + md5: fcb489df604d100968b737f2cb6076c6 + license: LicenseRef-Public-Domain + run_exports: {} + size: 118849 + timestamp: 1784250406640 +- conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + sha256: 4ed83961876dc8844a6f0df49c07b408efbaea275ffb0b37133e24c006990b3a + md5: 9d9a39212a876e4bb751c1cc3927b678 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 133271 + timestamp: 1785906721507 +- conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + sha256: a00162ac4b2f68a6ddf23905e9d2fdb3ecd5abad51659f512539952a780d53ed + md5: 925ff9ab74f4b9262a28842766e9e7b1 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - c-ares >=1.34.8,<2.0a0 + size: 205559 + timestamp: 1787170041830 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.1.1-py314h0656537_3.conda + sha256: 493eb10ddcd00cf42151f1a6303b5b08a3641172861583fe2e128e9bbc1db3e2 + md5: 5502c80a2761fbc926dc5847b69b7f53 + depends: + - __osx >=11.0 + - libffi >=3.7.0,<3.8.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 292318 + timestamp: 1788485600231 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-50.0.2-py311hc027f23_0.conda + noarch: python + sha256: 99c82adba610df83bf0f47491adf6ced7ea7eafc703011a230ddfcfc89118081 + md5: 1d4e7183556210fc49be37acdca44076 + depends: + - python + - cffi >=2.0 + - __osx >=11.0 + - _python_abi3_support 1.* + - cpython >=3.11 + - openssl >=3.5.8,<4.0a0 + constrains: + - __osx >=11.0 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + run_exports: {} + size: 1819278 + timestamp: 1790790581781 +- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + sha256: 3abd86f3441f143b6b3203c92ae0d88dd8396a8857940af468f1fab854cdae57 + md5: f13f4740c18b562bf2662d494bad6099 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14223209 + timestamp: 1786545868538 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20260526.0-cxx17_h6e8c311_3.conda + sha256: ffde056b097f48eab3f02e477e67c6f499acb267d5856396e768ba8b9bc9414e + md5: 86d4185cfb24d9e604f424ec72bf217f + depends: + - __osx >=11.0 + - libcxx >=19 + constrains: + - abseil-cpp =20260526.0 + - libabseil-static =20260526.0=cxx17* + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - libabseil >=20260526.0,<20260527.0a0 + - libabseil =*=cxx17* + size: 1273256 + timestamp: 1791681577753 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.2.0-he0616a4_4.conda + sha256: 14560b40c2c318f76ea517452f810ae9b9b752a75014138ff1ad06dba7c7e55d + md5: faa59453024554888f67ac3142f6e4f4 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + size: 78827 + timestamp: 1788480981901 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.2.0-h4a2f56c_4.conda + sha256: 61d001395c040d0879bc25e1a012f0d80dff315a3b96da1f4018a6815341442a + md5: 23362431ccf826a88ea0bdefd2ffa9dd + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 he0616a4_4 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 31518 + timestamp: 1788481027514 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.2.0-h3d41943_4.conda + sha256: fb3c5a415789e7cbd6a6cd2453716ab18c360a66e46a8e2abb8b99b719535bb7 + md5: c9d01f04f03fff927a846e1985a89383 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 he0616a4_4 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 + size: 312039 + timestamp: 1788481058122 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + sha256: 19ec3adf903c04aac6f31b180d283f0beb6d0393c5c1603f1d57355eb3a8fd66 + md5: 55664c771bbae09ac41bd7c940c3a7e1 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 573303 + timestamp: 1791337833929 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + sha256: 223314a7476bdeb00f698937b6960fc51cb98627af2ac5a629e5150bcddb8abf + md5: 6d2f0447151b390bdaed846e143272e3 + depends: + - __osx >=11.0 + license: BSD-2-Clause OR GPL-2.0-or-later + license_family: GPL + run_exports: + weak: + - libev >=4.33,<4.34.0a0 + size: 40479 + timestamp: 1785917395373 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + sha256: c58d84e9455db8161fa6a2413c1bf11de30682c02f9a3c1ddfaf24ea73dbe10f + md5: 082b0cec641dcb5bbf71d2aa4b37bfd4 + depends: + - __osx >=11.0 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 75347 + timestamp: 1790370393156 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + sha256: c4793041226c87f987b9903e6503b76f02f52855cc193be2729ac127e600529b + md5: e077b71ae65754eda067e4125364b905 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 60786 + timestamp: 1787754056669 +- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + sha256: 7915dac7c71c208e40e716e2f6d3eff41a8d5584e0e7c2d46f9bf9bd5f9aa739 + md5: daf49067580fbfeae3ac7f9535400494 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 104919 + timestamp: 1786349094608 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + sha256: 6438d0ef76e81f2b75ad7599685a525407c1d9fb2d6a7c18f360614ae6807970 + md5: b10a43915a31193e06b2781b9d11aec3 + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 79639 + timestamp: 1786651070313 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + sha256: 2d5c131553e83089be74988529d758e2a6dbb9227056d8fa19c01f5ccef6e6fc + md5: b7c605bed8006cdeb822dd7de6ac87c7 + depends: + - __osx >=11.0 + - c-ares >=1.34.8,<2.0a0 + - libcxx >=21 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 + size: 598607 + timestamp: 1787178086085 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + build_number: 101 + sha256: 00fa627d39047acaee98bac32821cc5dac92c60a49b3e62f1ad7cb8d03c2187e + md5: 466f99da218bc7b6713db0d5404ca8d5 + depends: + - __osx >=11.0 + - libcxx >=20 + license: Python-2.0 + run_exports: + weak: + - libpython >=3.14,<4.0a0 + size: 2120464 + timestamp: 1791334549048 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.54.0-h59ff3a2_1.conda + sha256: dbe909ef285f187406569b805e97e668722345ab7efd82c67d4d9dd983c8b715 + md5: 50d4b8bfefcbd6711364a970dc810325 + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.54.0,<4.0a0 + size: 1024450 + timestamp: 1791584934366 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + sha256: 4aacf651487bf2cd4dcfab49ea98a00a34305919ff3a09b66b7ddaa97d8b316f + md5: 17b0d6c818992264752f1a720be711fc + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 128560 + timestamp: 1785914631885 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + sha256: b2dba286dd6632292b12296e761193b5ef9fb0eaeecaa481f5ba9af72c0c18e1 + md5: 7d3fa28263bb7f8ea32db11f570a5bb6 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 58993 + timestamp: 1785276808631 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + sha256: 12c1d676b9a0e8109b576672519312c5428308f3f3d7706f8717e2f536d5d9e7 + md5: 88a79390f87c8f3334b9999a892e78d4 + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 834865 + timestamp: 1786356957789 +- conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-26.10.0-hb4a83e6_0.conda + sha256: 7c8905323508b0b0933c7e2f989dd2e4fc889764cd40c1f3b049dd47427d99cc + md5: 947927ccab36a40542314545ef84e4f3 + depends: + - libcxx >=21 + - __osx >=12.0 + - c-ares >=1.34.8,<2.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libzlib >=1.3.2,<2.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libuv >=1.52.1,<2.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libabseil >=20260526.0,<20260527.0a0 + - libabseil * cxx17* + - openssl >=3.5.8,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + - icu >=78.3,<79.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - nodejs >=26.10.0,<27.0a0 + size: 19872219 + timestamp: 1790238494442 +- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + sha256: d992d27aec2f1beac81f792c85b449546c030f06937b5b3ea7cf58431861dde4 + md5: 615ac6cff316565b442cd1af8b94837f + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 2786968 + timestamp: 1791099439455 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + build_number: 101 + sha256: 91874ead4971c6d3b5a2b50b25c34ce8a312f2aa6a862469547c6e4d8b5af2f6 + md5: a66d7bb9eb54ce5939e5b0993d228bc5 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 hfe304d0_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 12690138 + timestamp: 1791334717743 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + sha256: feb9248a062b7a0738e56339d8c9e87bc9adf8e8c76549fb55b0b2456bec3a57 + md5: 434eb49340f57827ef7ca3bb21f77c32 + depends: + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 319279 + timestamp: 1787034454836 +- conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-2026.9.1-py314h3cfb53e_0.conda + sha256: de979ff36d1946a1728e3bb61f10dd353514b1fa8724447d35018b6a6d2c989f + md5: 8d50f16e18f7bc1f0008a9a38a918db9 + depends: + - python + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: {} + size: 302047 + timestamp: 1791202491493 +- conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + sha256: 74e5fabcaf6ca0db052c645646ea04ded98a5eb7540483217f8101a819eb3107 + md5: 71c9f1f0267f2639523e898c6b50a4dc + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3512384 + timestamp: 1787272935349 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + sha256: 5277886d9704a624dc9b79ac985861e1e431bdb39a57c082507ab577a138ec6c + md5: c1d11f04327e40537ffe6cad5b131019 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 528228 + timestamp: 1786599702092 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + sha256: 8ec22f0ba25cbfc2e64d70cf29459eccd7ffdf6436f6a6ff15bbfef799f7d4f6 + md5: b50612e7d190b8061ab4e7dc119cf4d5 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 124965 + timestamp: 1785906749812 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + sha256: 82bdd5a3fcada6afef6255a9bf41172f07b362f36e04a354dc2abc0a29bfb756 + md5: 4cc01a374215de38387d45e19c8c5c9c + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - c-ares >=1.34.8,<2.0a0 + size: 197819 + timestamp: 1787169996553 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.1.1-py314h618e29d_3.conda + sha256: 172fcb9649244b38083d3242550841e9b24fafeb5530ea125b44f364172f4e9d + md5: 1177738698334efc54d4e9a2f108c469 + depends: + - __osx >=11.0 + - libffi >=3.7.0,<3.8.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 292373 + timestamp: 1788485305495 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-50.0.2-py311hc28ac56_0.conda + noarch: python + sha256: 0c681f12351d4942decede4ef431f4d4f27720da76c49f0a43f351275eca0bca + md5: db8c959446b5085b7ae417e0d34ddc38 + depends: + - python + - cffi >=2.0 + - __osx >=11.0 + - openssl >=3.5.8,<4.0a0 + - _python_abi3_support 1.* + - cpython >=3.11 + constrains: + - __osx >=11.0 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + run_exports: {} + size: 1770710 + timestamp: 1790790523277 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + sha256: 6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416a43 + md5: a5efc0b42bb8b42e97d0a29ae3e3c187 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14070242 + timestamp: 1786545847761 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260526.0-cxx17_h4c27e2a_3.conda + sha256: 27859d85276442961b01bcfc488dc85426109330ffb157d3224772a7eaa72a75 + md5: 009ec10961e8426182e9d4c33e31db55 + depends: + - __osx >=11.0 + - libcxx >=19 + constrains: + - abseil-cpp =20260526.0 + - libabseil-static =20260526.0=cxx17* + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - libabseil >=20260526.0,<20260527.0a0 + - libabseil =*=cxx17* + size: 1277648 + timestamp: 1791681045738 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-h1dcdb26_4.conda + sha256: 8a6e4789a6049dabb41c6fcaf6719232245484d81dfeb199b5abdb95c84c9fc2 + md5: 8f3981871d167a6cd323e636e1929dd4 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + size: 79648 + timestamp: 1788480342707 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-h5295a6a_4.conda + sha256: 4e1f5989561de4546209b42c935795a41fa4265e0b670861480f1adffec623a8 + md5: da537a1643ef3e13bdccf16cca206f2c + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 h1dcdb26_4 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 29864 + timestamp: 1788480352084 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-h2ddc9cb_4.conda + sha256: 4d2da97825b221054a39f492e4dffe361e1931c8381d0367f1e0598a50d02f34 + md5: 39a25d500b191c16996239c4afa104f1 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 h1dcdb26_4 + license: MIT + license_family: MIT + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 + size: 295505 + timestamp: 1788480359341 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + sha256: 2d9d31172d7919bd276a8d1be338de567dd5afdd181e8d3d3d8c2d8695e09de2 + md5: 424521e52e65ef7f6cf957c4966e6386 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 577501 + timestamp: 1791337239735 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + sha256: c0100064506ae8abb432c5a506d474f10af2cf48c33d62bc221fb28b6d6ff6ac + md5: 19e86c8a6a47e92bb2e70ca12e758c5c + depends: + - __osx >=11.0 + license: BSD-2-Clause OR GPL-2.0-or-later + license_family: GPL + run_exports: + weak: + - libev >=4.33,<4.34.0a0 + size: 39991 + timestamp: 1785917376956 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + sha256: 50aa761b83fc7a116ca88fe0cb4cefce5abababb10a926bf8afbafd5c298d102 + md5: 5383c550b785bdaafcc4eaf638071a7c + depends: + - __osx >=11.0 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 69565 + timestamp: 1790370026495 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + sha256: 2783389a7b9dda04c62cc54c6bbeb03dd3cef24b3fc642715d02a3fa19464a9a + md5: 216bbcc23c11e9695b3db4a8771d76eb + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 43637 + timestamp: 1787753403688 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + sha256: 23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4311 + md5: 8ab10323068b107661a4b9a4af84f3b5 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 91720 + timestamp: 1786348695846 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + sha256: 04cc136c5a956a73aa14e0a160b5822b0b29714e67b299fa1b1fd16dbcba5366 + md5: ff33a4dbd93abc8a798cc4e0e7c8136d + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 73289 + timestamp: 1786651074391 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + sha256: 445440d8cccccb6585f71d1eb7c949d64a2af2ced5481d924621424ff3b6a398 + md5: ac9902dcbe0417f50cf95ab2bde062fa + depends: + - __osx >=11.0 + - c-ares >=1.34.8,<2.0a0 + - libcxx >=21 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 + size: 567024 + timestamp: 1787177422467 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + build_number: 101 + sha256: 257d8491de0514a5da3b3fd0d81a64802df6a7e3a72c31d639bd92d0cb110a0f + md5: af47f048c7a22af82a66a912794fe4ee + depends: + - __osx >=11.0 + - libcxx >=20 + license: Python-2.0 + run_exports: + weak: + - libpython >=3.14,<4.0a0 + size: 1895946 + timestamp: 1791332518303 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.54.0-hca69786_1.conda + sha256: 35e9265b836367ebf75982051a21cf124d0dd6967da628d9356b8aa433cc6947 + md5: 4219b7c43075bdc152b1db4cd0e46828 + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.54.0,<4.0a0 + size: 953259 + timestamp: 1791584347161 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + sha256: 4f47de9de1990efd998edbbd6793f89c8f02ffde987ae8120b1c006acefd2a04 + md5: de09bd0f175611e94f21b28f8c708e80 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 122729 + timestamp: 1785914645797 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + sha256: a18fa5d5bac452401459f966cf0d872224e8080c4ff93c77e168d43ab42ef9d7 + md5: f39288f0ea63ae962e1a2e4f355a0d75 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 47822 + timestamp: 1785277049190 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + sha256: 7024a48c8c0d0114ed4ab53c76bf9275d50e91ba7cea367a9aead638d3c29c68 + md5: 3dfa0d0316dc246cd44937a557de4501 + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 804298 + timestamp: 1786355189145 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-26.10.0-h8d74fab_0.conda + sha256: e08552a430a3683f1cbc3bc8934449e301cd3ad6cc38fe34627de0301893ab44 + md5: 2f4e4682e0a68bd0e15a7964d6ceb73b + depends: + - __osx >=12.0 + - libcxx >=21 + - c-ares >=1.34.8,<2.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libsqlite >=3.53.4,<4.0a0 + - openssl >=3.5.8,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + - icu >=78.3,<79.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - libuv >=1.52.1,<2.0a0 + - libabseil >=20260526.0,<20260527.0a0 + - libabseil * cxx17* + license: MIT + license_family: MIT + run_exports: + weak: + - nodejs >=26.10.0,<27.0a0 + size: 18529792 + timestamp: 1790238394580 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + sha256: 44fbc526456571a9fb8fa18157f6f269d4d4bd40eef20183a93b9c9296f94497 + md5: 45d9179cdf6e53d88aec034246f0dad6 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 3111573 + timestamp: 1791097959641 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + build_number: 101 + sha256: 4aebb9d626b26a2f7257d3c671bac70a96fffd4706db4d61c35f7bda6bee74f3 + md5: db895757bd372efa32f96937fabb3ef0 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 h4311e70_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 12496923 + timestamp: 1791332554767 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + sha256: d6782b430e6dce4fe8c7ac118cd988d5a193eb4a7f60741edfaede58016b6110 + md5: 9347fd56a002e6b58946831d48fe62f6 + depends: + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 314395 + timestamp: 1787033878899 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.9.1-py314hc05cd11_0.conda + sha256: f8b96fa257e9f34af1168d1321ae6ef3ce7211d684fb429c4cbbe425583f9014 + md5: 4faa708a07c8ec44c08c3b2e9fb0e110 + depends: + - python + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: {} + size: 286096 + timestamp: 1791202353806 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + sha256: 857d89087ae7f2c328cf256728affcb7343031a148b4af847334d248a9cf564c + md5: 90a01bf394d1c594e0eb9258f967d828 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3342183 + timestamp: 1787272852357 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + sha256: da867f5092eb0cb746d353694f0098031fd9817a4ce7d5743121209ae0f406ca + md5: 4ec2684c73812cc2c3d78379384a39cc + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 433687 + timestamp: 1786599629846 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 0000000..b9f51ed --- /dev/null +++ b/pixi.toml @@ -0,0 +1,33 @@ +[workspace] +name = "paperspec" +version = "0.1.0" +description = "The scienting data formats: specification, JSON Schemas, SQL, test vectors and fixtures" +authors = ["Scientific Computing Studio "] +license = "CC-BY-4.0 AND CC0-1.0 AND Apache-2.0" +license-file = "LICENSE.md" +readme = "README.md" +homepage = "https://paperspec.scient.ing" +repository = "https://git.scient.ing/infra/paperspec" +documentation = "https://paperspec.scient.ing/docs/" +channels = ["conda-forge"] +platforms = ["linux-64", "linux-aarch64", "osx-64", "osx-arm64"] +requires-pixi = ">=0.40" + +[dependencies] +python = ">=3.14,<3.15" +jsonschema = ">=4.26.0" +markdownlint-cli2 = ">=0.23.3" +nodejs = ">=22" +cryptography = ">=46" + +[tasks] +check = { cmd = "python tools/check.py", depends-on = [ + "lint", +], description = "Check schemas, records, packages, vectors, a byte-for-byte rebuild, the SQL round trip, prose and links" } +quick = { cmd = "python tools/check.py --quick", description = "Check everything except the byte-for-byte rebuild" } +build = { cmd = "python tools/build.py", description = "Rebuild fixtures/ and vectors/ from fixtures/src/ and the oracle" } +lint = { cmd = "markdownlint-cli2", description = "Lint every Markdown file with markdownlint" } +load = { cmd = "python tools/load.py", description = "Load packages into SQLite: pixi run load --sqlite lab.db PACKAGE..." } +validate = { cmd = "python tools/validate.py", description = "Validate packages, or run proposed corrections through the gate" } +stress = { cmd = "python tools/stress.py", description = "Stress the oracle with random inputs: pixi run stress -- --seed N" } +site = { cmd = "python tools/site.py", description = "Build the website into _site/" } diff --git a/registry/README.md b/registry/README.md new file mode 100644 index 0000000..f98d64e --- /dev/null +++ b/registry/README.md @@ -0,0 +1,86 @@ +# Registry + +The registry holds lists that tools read at run time. +Each list is a data file, so a reader, writer, converter or checker loads it instead of copying it into code, and a team can change a list without changing a program. +This page is for newcomers, implementers who need the exact behavior, and experts who want the status of each format. + +| File | Holds | +| --- | --- | +| `formats.json` | Every format: its identifier, media type (null for the six that have none), schema, status, chapter and a one-line description. | +| `rules.json` | Every validation rule ID, with what it means and the chapter that defines it. | +| `stamps/scienting-stamps-1.json` | The published rules that recognize the download stamps publishers add to PDFs (see Adding stamp rules), so page fingerprints ignore them. | +| `stages/scienting-stages-default.json` | The rights each processing stage needs, as a default a team may replace. | + +## Format status + +Each entry in `formats.json` has a `status`. +A `candidate` format is complete, with vectors and fixtures, and ready to implement. +It changes only with a recorded reason and a new or changed vector. +A `provisional` format is complete and expected to change as implementations gain experience, so it may change more freely. +At version 0.1.0, 19 of the 32 formats are `candidate` and 13 are `provisional`. +The third defined value, `reserved`, is unused. +The values are defined in [Chapter 0, section 0.4](../spec/00-introduction.md#04-status), and the stability rules in [Chapter 22, section 22.5](../spec/22-conformance.md#225-stability). + +## Registering the media types + +The `application/vnd.scienting.*` media types are vendor-tree types, which IANA registers on request without a standards document (RFC 6838 §3.2). +Register each type the formats serve over the web before the first release that other tools read: the zipped package, the anchor, the receipt and the layer first. +Until then the types are unregistered and work as they are; a registration changes no byte of any file. +The JSON-LD context is `application/ld+json` and a checkpoint is `text/plain`, both already registered. + +## Rule IDs + +A validator checks a package and reports each failure as `path:line: rule: message`, for example: + +```text +nodes.jsonl:6: doc.hash.node-hash: node_hash does not recompute +``` + +A `node_hash` is a hash (a fixed-length value computed from content, so any change to the content changes it) stored with each node of a document. +The line above is the failure that `fixtures/invalid/hash-mismatch/` is built to cause: its sixth node record carries a `node_hash` of all zeros. + +A rule's meaning never changes, and a retired rule's ID is never reused, so tools and people can rely on the IDs. +A tool can match on the `rule` field, whose meaning is looked up in `rules.json`, and treat the message as text for people. +[Chapter 22, section 22.4](../spec/22-conformance.md#224-rules) lists the ID prefixes. +Each directory in `fixtures/invalid/` has an `expect.json` that names the rule it breaks. +The reference checker (`tools/check.py`) fails if that rule is not in `rules.json`. + +## Adding stamp rules + +Many publishers add a line to each PDF they serve, naming the institution and the time of download. +This page calls that line a stamp. +Two downloads of one paper then differ, so a hash of the file cannot match them. +A page fingerprint is a hash of a page's size, its text and its images. +It is computed after removing every line that a stamp rule matches ([Chapter 7, section 7.1](../spec/07-geometry.md#71-page-fingerprints)). +The vectors in `vectors/fingerprints.jsonl` show this: `acs-download-1` and `acs-download-2` differ in the institution and the time on their stamp lines and have the same fingerprint. + +Suppose two downloads of one paper differ only in a stamp line that no published rule recognizes. +Record a rule in a file of your own, marked as learned: + +```json +{"format": "scienting-stamps/1", "id": "smithlab-learned", "learned": true, + "rules": [{"id": "licensed-to", "pattern": "^This copy is licensed to .+", "where": "margin", "margin": 36}]} +``` + +Normalized text is the line after Unicode Normalization Form C, with each run of whitespace replaced by one space and the ends trimmed ([Chapter 1, section 1.4](../spec/01-conventions.md#14-text-normalization-for-hashing)). + +A rule has an `id`, a `pattern`, and a `where` that is `any` or `margin`. +A `margin` rule matches only lines whose box lies wholly within `margin` points of one page edge (36 when the rule gives none). +Patterns use only syntax that ECMAScript and Python read alike, and match a line's normalized text, with the ASCII letters A to Z compared without case. +The allowed syntax is literals, `.`, `*`, `+`, `?`, `^`, `$`, classes and escaped punctuation. + +A page record in `pages.jsonl` lists, in `stamps_removed`, the IDs of the rules that removed lines. +A rule that is too broad hides a real difference between two pages. +A stamp that no rule recognizes splits one edition into two ([Chapter 7, section 7.2](../spec/07-geometry.md#72-stamp-rules)). + +## Replacing the stage defaults + +A stage is one step of processing, such as conversion or indexing. +Each stage needs certain rights, such as the right to mine text, and a stage runs only when the rights record of the paper allows them. +The stage requirements are configuration, not code, because what a team may do depends on how it holds each paper. + +A team copies `scienting-stages-default.json`, adjusts it with its counsel and points its project's settings at the copy. +The file itself calls its contents "proposed defaults from the design, for counsel to set". +In a project, the `settings.stages` field holds the `id` of the stage file in use ([Chapter 20](../spec/20-projects.md)), so a team's copy needs an `id` of its own. +The project format is `provisional`. +[Chapter 14](../spec/14-rights.md) explains how stages are checked. diff --git a/registry/formats.json b/registry/formats.json new file mode 100644 index 0000000..1257337 --- /dev/null +++ b/registry/formats.json @@ -0,0 +1,262 @@ +{ + "registry": "formats", + "version": "0.1.0", + "formats": [ + { + "format": "scienting-package/1", + "media_type": "application/vnd.scienting.doc+zip", + "schema": "manifest.schema.json", + "status": "candidate", + "chapter": "spec/12-package.md", + "description": "A package: MANIFEST.json and its files, a folder or a zip." + }, + { + "format": "scienting-doc/1", + "media_type": "application/vnd.scienting.doc+json", + "schema": "document.schema.json", + "status": "candidate", + "chapter": "spec/02-model.md", + "description": "A document: document.json, with nodes.jsonl and the package's other files." + }, + { + "format": "scienting-page/1", + "media_type": null, + "schema": "page.schema.json", + "status": "candidate", + "chapter": "spec/07-geometry.md", + "description": "The page fingerprint function, and a page record." + }, + { + "format": "scienting-anchor/1", + "media_type": "application/vnd.scienting.anchor+json", + "schema": "anchor.schema.json", + "status": "candidate", + "chapter": "spec/06-anchors.md", + "description": "A pinned address with enough context to survive change." + }, + { + "format": "scienting-correction/1", + "media_type": "application/vnd.scienting.correction+json", + "schema": "correction.schema.json", + "status": "candidate", + "chapter": "spec/11-corrections.md", + "description": "An operation on an established document." + }, + { + "format": "scienting-receipt/1", + "media_type": "application/vnd.scienting.receipt+json", + "schema": "receipt.schema.json", + "status": "candidate", + "chapter": "spec/08-fidelity.md", + "description": "A signature over a Merkle root of reviewed values." + }, + { + "format": "scienting-revocation/1", + "media_type": "application/vnd.scienting.revocation+json", + "schema": "revocation.schema.json", + "status": "candidate", + "chapter": "spec/08-fidelity.md", + "description": "A signed withdrawal of receipts." + }, + { + "format": "scienting-roster/1", + "media_type": "application/vnd.scienting.roster+json", + "schema": "roster.schema.json", + "status": "candidate", + "chapter": "spec/08-fidelity.md", + "description": "The keys that may sign, and for what." + }, + { + "format": "scienting-qa-report/1", + "media_type": "application/vnd.scienting.qa-report+json", + "schema": "qa-report.schema.json", + "status": "candidate", + "chapter": "spec/08-fidelity.md", + "description": "Reviewer error bounds for a delivery, signed." + }, + { + "format": "scienting-spot-check/1", + "media_type": null, + "schema": "spot-check.schema.json", + "status": "candidate", + "chapter": "spec/08-fidelity.md", + "description": "The input a spot-check key proves a VRF output for, to seed a sample; never a file of its own." + }, + { + "format": "scienting-proof/1", + "media_type": "application/vnd.scienting.proof+json", + "schema": "proof.schema.json", + "status": "candidate", + "chapter": "spec/08-fidelity.md", + "description": "An RFC 9162 inclusion proof for one item of a receipt, or a consistency proof between two revisions." + }, + { + "format": "scienting-rights/1", + "media_type": "application/vnd.scienting.rights+json", + "schema": "rights.schema.json", + "status": "candidate", + "chapter": "spec/14-rights.md", + "description": "A witness's license, basis and uses." + }, + { + "format": "scienting-policy/1", + "media_type": "application/vnd.scienting.policy+json", + "schema": "policy.schema.json", + "status": "candidate", + "chapter": "spec/14-rights.md", + "description": "A signed team decision that resolves unknown uses." + }, + { + "format": "scienting-stages/1", + "media_type": "application/vnd.scienting.stages+json", + "schema": "stages.schema.json", + "status": "candidate", + "chapter": "spec/14-rights.md", + "description": "The uses each stage needs." + }, + { + "format": "scienting-backend/1", + "media_type": "application/vnd.scienting.backend+json", + "schema": "backend.schema.json", + "status": "candidate", + "chapter": "spec/14-rights.md", + "description": "A tool's code and weight licenses and their conditions." + }, + { + "format": "scienting-profile/1", + "media_type": "application/vnd.scienting.profile+json", + "schema": "profile.schema.json", + "status": "candidate", + "chapter": "spec/14-rights.md", + "description": "What backend conditions ask about a team." + }, + { + "format": "scienting-stamps/1", + "media_type": "application/vnd.scienting.stamps+json", + "schema": "stamps.schema.json", + "status": "candidate", + "chapter": "spec/07-geometry.md", + "description": "Download-stamp line rules." + }, + { + "format": "scienting-suspect/1", + "media_type": null, + "schema": "suspect.schema.json", + "status": "candidate", + "chapter": "spec/05-hashes.md", + "description": "A doubtful reading for review." + }, + { + "format": "scienting-layer/1", + "media_type": "application/ld+json; profile=\"http://www.w3.org/ns/anno.jsonld\"", + "schema": "layer.schema.json", + "status": "candidate", + "chapter": "spec/18-layers.md", + "description": "A layer of W3C Web Annotations." + }, + { + "format": "scienting-exercise/1", + "media_type": null, + "schema": "exercise.schema.json", + "status": "provisional", + "chapter": "spec/19-exercises.md", + "description": "The body of an exercise annotation." + }, + { + "format": "scienting-submission/1", + "media_type": "application/vnd.scienting.submission+json", + "schema": "submission.schema.json", + "status": "provisional", + "chapter": "spec/19-exercises.md", + "description": "A student's answer under a pseudonym." + }, + { + "format": "scienting-grade/1", + "media_type": "application/vnd.scienting.grade+json", + "schema": "grade.schema.json", + "status": "provisional", + "chapter": "spec/19-exercises.md", + "description": "The grader's result." + }, + { + "format": "scienting-project/1", + "media_type": "application/vnd.scienting.project+json", + "schema": "project.schema.json", + "status": "provisional", + "chapter": "spec/20-projects.md", + "description": "A project." + }, + { + "format": "scienting-bundle/1", + "media_type": "application/vnd.sqlite3", + "schema": "sql/bundle-sqlite.sql", + "status": "provisional", + "chapter": "spec/13-database.md", + "description": "The SQLite bundle readers and servers query." + }, + { + "format": "scienting-dataset/1", + "media_type": "application/vnd.scienting.dataset+json", + "schema": "dataset.schema.json", + "status": "provisional", + "chapter": "spec/15-datasets.md", + "description": "A Frictionless Data Package with units, uncertainty and origin." + }, + { + "format": "scienting-digitization/1", + "media_type": "application/vnd.scienting.digitization+json", + "schema": "digitization.schema.json", + "status": "provisional", + "chapter": "spec/16-digitization.md", + "description": "How values were read off a figure panel." + }, + { + "format": "scienting-view/1", + "media_type": "application/vnd.vegalite+json", + "schema": "view.schema.json", + "status": "provisional", + "chapter": "spec/17-views.md", + "description": "A Vega-Lite view that pins its data." + }, + { + "format": "scienting-snapshot/1", + "media_type": "application/vnd.scienting.snapshot+json", + "schema": "snapshot.schema.json", + "status": "provisional", + "chapter": "spec/21-drafts.md", + "description": "What a draft cites, pinned." + }, + { + "format": "scienting-draft-ids/1", + "media_type": null, + "schema": "draft-ids.schema.json", + "status": "provisional", + "chapter": "spec/21-drafts.md", + "description": "A Typst project's sentence-ID sidecar." + }, + { + "format": "scienting-checklist/1", + "media_type": "application/vnd.scienting.checklist+json", + "schema": "checklist.schema.json", + "status": "provisional", + "chapter": "spec/08-fidelity.md", + "description": "A check of an export against a named standard, covered by a receipt." + }, + { + "format": "scienting-log-entry/1", + "media_type": null, + "schema": "log-entry.schema.json", + "status": "provisional", + "chapter": "spec/23-log.md", + "description": "One item of a team's transparency log: a receipt, revocation or roster by kind, ID and hash." + }, + { + "format": "scienting-checkpoint/1", + "media_type": "text/plain; charset=utf-8", + "schema": "checkpoint.schema.json", + "status": "provisional", + "chapter": "spec/23-log.md", + "description": "A signed checkpoint of a team's log: a signed note with the origin, size and root." + } + ] +} diff --git a/registry/rules.json b/registry/rules.json new file mode 100644 index 0000000..f2e89d7 --- /dev/null +++ b/registry/rules.json @@ -0,0 +1,497 @@ +{ + "registry": "rules", + "version": "0.1.0", + "note": "Rule IDs name each refusal, so tools report file, node and rule in the form path:line: rule: message.", + "rules": [ + { + "id": "correction.digits", + "description": "A digit changes without crop evidence, or a leaf's digits change undeclared.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.evidence", + "description": "An insert has no crop evidence.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.find", + "description": "`find` is empty or does not occur exactly once.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.insert", + "description": "Text is inserted outside the runs of a node, or at a bad offset.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.merge", + "description": "The nodes differ in kind, are not mergeable, or are not adjacent siblings.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.move", + "description": "The destination is unknown or inside the moved node.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.op", + "description": "The operation is unknown.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.reclassify", + "description": "The new kind has another content shape.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.relabel", + "description": "The kind takes no label.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.replace", + "description": "Runs replace text outside a text run, or include an equation run.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.schema", + "description": "A proposed correction does not match the correction schema.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.set", + "description": "The attribute cannot be set on the kind.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.split", + "description": "The node is not a sentence, the offset is outside it or inside a run other than text, or a part is empty.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "correction.target", + "description": "A target, parent or sibling is not a live node, or the root is deleted, moved, merged or reclassified.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.correction.after", + "description": "The last correction of a leaf does not end at the leaf's current node_hash.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.correction.id", + "description": "A correction's id does not derive from its record.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.correction.index", + "description": "Correction indexes do not count from 1 without gaps.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.correction.rev", + "description": "document.json's rev is not the number of corrections.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.fidelity.report", + "description": "document.json's fidelity distribution does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.align-key", + "description": "An align_key does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.algorithm", + "description": "document.json names no hash algorithm, or one the consumer does not implement.", + "chapter": "spec/01-conventions.md" + }, + { + "id": "doc.roster.did", + "description": "A roster key's did:key is not the one its public key determines.", + "chapter": "spec/08-fidelity.md" + }, + { + "id": "doc.hash.key", + "description": "The key supplied does not match the package's key_id.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.match-hash", + "description": "A match_hash does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.meta", + "description": "meta_hash does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.node-hash", + "description": "A node_hash does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.own-hash", + "description": "An own_hash does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.root", + "description": "document.json's root is not the root node's node_hash.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.hash.text-hash", + "description": "A text_hash does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.id.alias", + "description": "An alias does not name a live node.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.id.form", + "description": "An ID is not seven letter-first Crockford base32 characters.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.id.retired-live", + "description": "An ID is both live and in the ID table.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.id.retired-missing", + "description": "A correction retired an ID that ids.jsonl does not record.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.id.successor", + "description": "A successor names an ID that is neither live nor in the ID table.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.id.unique", + "description": "An ID occurs twice.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.location.node", + "description": "A location names an unknown node.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.location.page", + "description": "A location's page_fp is not a page of any witness.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.node.attrs", + "description": "A section has no level.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.node.content", + "description": "A node's content does not have the shape its kind requires.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.node.kind", + "description": "A node kind is not in the list.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.node.label", + "description": "A node of a kind that takes no label has one.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.node.schema", + "description": "A node a correction produced does not validate against the node schema (a property the kind does not take, or a bad shape).", + "chapter": "spec/11-corrections.md" + }, + { + "id": "doc.counts", + "description": "document.json's counts are not the number of nodes and of leaves.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.history", + "description": "document.json's history is not the root of the tree over the package's corrections.", + "chapter": "spec/11-corrections.md" + }, + { + "id": "doc.key.work", + "description": "The document key does not begin with the work key, or its suffix is not a version suffix.", + "chapter": "spec/02-model.md" + }, + { + "id": "doc.key.suffix", + "description": "The work key's hash part is not the hash of the work's identifier.", + "chapter": "spec/02-model.md" + }, + { + "id": "doc.order.ids", + "description": "ids.jsonl is not aliases by ID, then retirements by revision and ID.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.order.locations", + "description": "locations.jsonl is not sorted by node order, page and fingerprint.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.order.pages", + "description": "pages.jsonl is not sorted by witness and page.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.order.receipts", + "description": "receipts.jsonl is not sorted by time and ID.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.order.references", + "description": "references.jsonl does not follow document order.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.order.suspects", + "description": "suspects.jsonl is not sorted by ID.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.page.witness", + "description": "A page names an unknown witness.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.policy.keyed", + "description": "A checks-only package carries plain hashes.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.policy.withheld", + "description": "Text is present where the policy withholds it, or withheld where the policy is full, or a checks-only package carries corrections or suspects.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.qa.key", + "description": "A spot-check seed key is not a registered Ed25519 spot-check key, or was registered after the receipt.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.qa.of", + "description": "A spot-check names a receipt the package does not hold.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.qa.sample", + "description": "A spot-check sample does not follow from its seed.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.qa.seed", + "description": "A spot-check seed is not the checker's signature over the receipt.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.receipt.doc", + "description": "A receipt names another document.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.receipt.id", + "description": "A receipt's or revocation's id does not derive from its record.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.receipt.nodes", + "description": "A receipt's nodes are not sorted by ID, or one repeats.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.receipt.root", + "description": "A receipt's Merkle root does not recompute.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.receipt.signature", + "description": "A signature does not verify against the roster.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.reference.node", + "description": "A reference record names a node that is not a reference.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.run.canonical", + "description": "Runs are not canonical: an empty text run, or two adjacent text runs with the same styles.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.run.cite", + "description": "A cite run names a node that is not a reference.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.run.equation", + "description": "Equation runs do not name the sentence's equation children, once each, in order.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.run.fnmark", + "description": "An fnmark run names a node that is not a footnote.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.run.kind", + "description": "A run kind is not in the list.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.run.style", + "description": "A style is unknown, or a run is both a subscript and a superscript.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.run.xref", + "description": "A same-document xref names no node.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.table.header", + "description": "A column or row header path names a node that is not a cell.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.tree.child", + "description": "A node holds a child kind it may not hold, a heading is not first, or a once-only child repeats.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.tree.empty", + "description": "A kind that must have children has none.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.tree.ord", + "description": "A parent's children do not have ord 0 to n-1.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.tree.order", + "description": "nodes.jsonl is not in document order.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.tree.root", + "description": "The tree does not have exactly one root, of kind document.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "doc.witness.id", + "description": "A witness ID does not derive from its SHA-256.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "grade.key-stale", + "description": "An anchor in the exercise's key is stale, so nothing is graded with it.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "grade.kind", + "description": "The exercise kind is unknown.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.file.canonical", + "description": "A JSON or JSON Lines record is not in canonical JSON.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.file.empty", + "description": "An optional JSON Lines file is present with no records.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.file.newline", + "description": "A line of a JSON Lines file does not end with a newline.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.file.required", + "description": "document.json, nodes.jsonl, witnesses.json or provenance.json is missing.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.absent", + "description": "An entry listed without its bytes is not an asset, or its bytes are present.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.hash", + "description": "A file's SHA-256 or size differs from its manifest entry.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.key", + "description": "The manifest's key differs from document.json's.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.missing", + "description": "The package has no MANIFEST.json.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.missing-file", + "description": "A file the manifest lists is not in the package.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.order", + "description": "Manifest entries are not sorted by path, or a path repeats.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.schema", + "description": "MANIFEST.json does not validate against manifest.schema.json.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.manifest.unlisted", + "description": "The package holds a file the manifest does not list.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.path.unsafe", + "description": "A path is absolute, has an empty, `.` or `..` segment, a backslash or a NUL, is not normalized, or is or passes through a symbolic link.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.size", + "description": "The package's files exceed the consumer's size limit.", + "chapter": "spec/12-package.md" + }, + { + "id": "package.schema", + "description": "A file or line does not validate against its schema.", + "chapter": "spec/22-conformance.md" + }, + { + "id": "package.zip.entry", + "description": "A zipped package is not a zip archive, or an entry is encrypted, a symbolic link, neither stored nor deflated, not marked as UTF-8, duplicated, unsafe as a path, or not under one top-level folder named by the key.", + "chapter": "spec/12-package.md" + }, + { + "id": "package.zip.size", + "description": "A zipped package expands past the consumer's limit, or an entry holds more than its header declares.", + "chapter": "spec/12-package.md" + } + ] +} diff --git a/registry/stages/scienting-stages-default.json b/registry/stages/scienting-stages-default.json new file mode 100644 index 0000000..fb07e65 --- /dev/null +++ b/registry/stages/scienting-stages-default.json @@ -0,0 +1,85 @@ +{ + "format": "scienting-stages/1", + "id": "scienting-stages-default", + "note": "Proposed defaults from the design, for counsel to set. Configuration, not code: a team may replace this file.", + "stages": { + "convert-model": { + "uses": [ + "tdm" + ], + "ai": { + "purpose": "internal" + }, + "note": "Conversion by any model, local or outside." + }, + "convert-deterministic": { + "uses": [ + "tdm" + ], + "note": "The text-layer witness, segmentation, hashing and the gate." + }, + "index": { + "uses": [ + "tdm" + ], + "note": "The full-text index." + }, + "review-model": { + "uses": [], + "ai": { + "purpose": "internal" + }, + "note": "Model review of suspects, in a job zip or the direct API mode." + }, + "propose-model": { + "uses": [], + "ai": { + "purpose": "internal" + }, + "note": "Glosses, digitizations or claims a model proposes." + }, + "mcp-text": { + "uses": [], + "ai": { + "purpose": "internal" + }, + "note": "A text-serving interface returning text to the team's model." + }, + "embed": { + "uses": [], + "ai": { + "purpose": "internal", + "processors": [ + "local", + "tenancy" + ] + }, + "note": "Embeddings for search." + }, + "ai-data-external": { + "uses": [], + "ai": { + "purpose": "external" + }, + "note": "AI data built for others; in practice CC BY papers only." + }, + "read": { + "uses": [ + "read" + ], + "note": "Reading in the reader." + }, + "publish-quotes": { + "uses": [ + "quote-public" + ], + "note": "Publishing anything with quotations." + }, + "accessible-copy": { + "uses": [ + "accessible-copy" + ], + "note": "An accessible copy for a user with a disability." + } + } +} diff --git a/registry/stamps/scienting-stamps-1.json b/registry/stamps/scienting-stamps-1.json new file mode 100644 index 0000000..e24db7f --- /dev/null +++ b/registry/stamps/scienting-stamps-1.json @@ -0,0 +1,39 @@ +{ + "format": "scienting-stamps/1", + "id": "scienting-stamps-1", + "learned": false, + "note": "Published stamp-line rules, version 1. Patterns are matched against the normalized line, case-insensitively over ASCII. Teams add learned rules in files of their own.", + "rules": [ + { + "id": "downloaded-via", + "pattern": "^Downloaded via .+ on .+", + "where": "any", + "note": "The institution-and-time stamp some publishers print in the margin." + }, + { + "id": "downloaded-from-on", + "pattern": "^Downloaded from .+ on .+", + "where": "any", + "note": "The URL, institution and date stamp other publishers print." + }, + { + "id": "sharing-guidelines", + "pattern": "^See https?://pubs\\.acs\\.org/sharingguidelines", + "where": "any", + "note": "A sharing notice printed beside a download stamp." + }, + { + "id": "terms-and-conditions", + "pattern": "^See the Terms and Conditions \\(https?://onlinelibrary\\.wiley\\.com/", + "where": "any", + "note": "The rest of a stamp line, when a text layer splits it." + }, + { + "id": "margin-downloaded", + "pattern": "^Downloaded", + "where": "margin", + "margin": 36, + "note": "Any line in the outer 36 points that begins with Downloaded." + } + ] +} diff --git a/schemas/README.md b/schemas/README.md new file mode 100644 index 0000000..0f231a5 --- /dev/null +++ b/schemas/README.md @@ -0,0 +1,88 @@ +# Schemas + +This folder holds the JSON (JavaScript Object Notation) Schemas (draft 2020-12) for every file and record that the paperspec formats (paperspec is the specification this repository holds) define: 42 schema files. +A JSON Schema is a file, itself written in JSON, that states what a valid JSON file looks like. +Newcomers can read it as a form: it lists the fields a record must have and what kind of value each field takes. +Implementers will find the loading recipe and the traps under "Validating" and "Writing schemas". +Experts will find the chapter and status of each format under "Which schema for which file" and "What a schema does not check". + +Each schema's `$id`, its own address as a name, is `https://paperspec.scient.ing/schemas/`. +Schemas refer to each other by those names, and a validator (a program that checks a file against a schema) that loads the whole folder resolves every reference. +The `$id` base is normative and stays as it is. +The `scienting-` prefix on format identifiers such as `scienting-anchor/1` is the formats' namespace, a separate matter from the repository's name. + +## Which schema for which file + +The schemas are grouped by topic below. +The number after each name is the chapter of `spec/` that defines the file. +`common.schema.json` is defined in `spec/01-conventions.md`, the chapter on rules that apply to every format. + +| Topic | Schemas (chapter) | +| --- | --- | +| Shared definitions | `common.schema.json` (1): hashes, IDs, keys, addresses, times, decimals, boxes, licenses, signatures, evidence, quotes. | +| A package | `manifest.schema.json` (12), `document.schema.json` (2, 12), `node.schema.json` (3), `runs.schema.json` (3), `witnesses.schema.json` (2), `provenance.schema.json` (12), `page.schema.json` (7), `location.schema.json` (7), `reference.schema.json` (10), `id-entry.schema.json` (4), `correction.schema.json` (11), `receipt.schema.json` (8), `revocation.schema.json` (8), `roster.schema.json` (8), `suspect.schema.json` (5), `mathml.schema.json` (12) | +| Pointing into documents | `anchor.schema.json` (6) | +| Rights | `rights.schema.json` (14), `policy.schema.json` (14), `stages.schema.json` (14), `backend.schema.json` (14), `profile.schema.json` (14), `stamps.schema.json` (7) | +| Review | `qa-report.schema.json` (8), `spot-check.schema.json` (8), `checklist.schema.json` (8), `proof.schema.json` (8, 11) | +| The transparency log | `log-entry.schema.json` (23), `checkpoint.schema.json` (23) | +| Annotation and teaching | `layer.schema.json` (18), `annotation.schema.json` (18), `exercise.schema.json` (19), `submission.schema.json` (19), `grade.schema.json` (19) | +| Data | `dataset.schema.json` (15), `value-anchor.schema.json` (15), `digitization.schema.json` (16), `view.schema.json` (17) | +| Teams and drafts | `project.schema.json` (20), `snapshot.schema.json` (21), `draft-ids.schema.json` (21) | + +A record that travels on its own carries a `format` such as `scienting-anchor/1`. [registry/formats.json](../registry/formats.json) maps each format to its schema, its chapter and its status. + +The formats registry lists 32 formats: 19 are `candidate` (complete, with vectors and fixtures, ready to implement) and 13 are `provisional` (complete; expected to change as implementations gain experience), as defined in `spec/00-introduction.md` §0.4. +The provisional formats are `scienting-project/1`, `scienting-bundle/1`, `scienting-dataset/1`, `scienting-digitization/1`, `scienting-view/1`, `scienting-snapshot/1`, `scienting-draft-ids/1`, `scienting-exercise/1`, `scienting-submission/1`, `scienting-grade/1`, `scienting-checklist/1`, `scienting-log-entry/1` and `scienting-checkpoint/1`. +The Data schemas for datasets, digitizations and views, the Teams and drafts schemas, the three teaching schemas, `checklist.schema.json` and the two log schemas belong to provisional formats. +The rest belong to `candidate` formats or to no format of their own. + +The bundle has no JSON Schema: its registry entry points to `sql/bundle-sqlite.sql`. +Of the 42 schemas, 11 have no format of their own because each describes a line or part of a larger file: `common`, `node`, `runs`, `witnesses`, `provenance`, `location`, `reference`, `id-entry`, `mathml`, `annotation` and `value-anchor`. +Of the schemas that do have one, 27 require a `format` property; `spot-check.schema.json` describes the input a VRF proof is made over rather than a file. +The others (`page`, `draft-ids`, `view` and `log-entry`) describe a line of a file, a Vega-Lite specification (a JSON description of a chart) or an item of a tree, and the record itself does not need to carry the identifier. + +## Validating + +The example below uses the `jsonschema` package (4.18 or later). + +```python +import json, pathlib +from jsonschema import Draft202012Validator +from referencing import Registry, Resource + +schemas = {p.name: json.loads(p.read_text()) for p in pathlib.Path("schemas").glob("*.json")} +registry = Registry().with_resources((s["$id"], Resource.from_contents(s)) for s in schemas.values()) +validator = Draft202012Validator(schemas["anchor.schema.json"], registry=registry) +validator.validate(json.load(open("fixtures/records/anchor-span.json"))) +``` + +It raises no error when run from the repository root, since `anchor-span.json` is a valid anchor. +A schema refers to another by a relative name, and the `Registry` object resolves it. +Here `anchor.schema.json` points to `common.schema.json#/$defs/key`, which a validator resolves against the `$id` above into `https://paperspec.scient.ing/schemas/common.schema.json`. +The `Registry` maps that name to the file's contents, so nothing is fetched over the network. +`Draft202012Validator(schemas["anchor.schema.json"])` fails with `Unresolvable: common.schema.json#/$defs/key` when the `Registry` is missing. +Never load a schema alone. + +Any draft 2020-12 validator works the same way: give it every schema under its `$id`, then validate against the one you need. +`python3 tools/check.py` validates every fixture with `jsonschema` this way, and checks that every schema keeps to the keyword subset. + +## What a schema does not check + +A schema checks shape: required properties, types, patterns, enumerations. +The anchor in `fixtures/records/anchor-span.json` has a `node_hash` (a fingerprint of the node's content) of 64 lowercase hex digits, and a schema can confirm exactly that. +It cannot confirm that the hash is the right one: replace it with 64 zeros and the record still validates. +It also cannot check that a node's children are allowed or that a receipt's signature verifies, nor that a correction's ID derives from its content. +The rules of [spec/22-conformance.md](../spec/22-conformance.md) cover these checks, each with an ID in [registry/rules.json](../registry/rules.json). +For the four examples the IDs are `doc.hash.node-hash`, `doc.tree.child`, `doc.correction.id` and `doc.receipt.signature`. + +A validator that reports `package.schema` has found only a shape error. +The other rules need the chapters' computations, and the test vectors in `vectors/` (for example `hashes.jsonl`, `corrections.jsonl` and `signatures.jsonl`) give the expected outputs. +The schemas are normative, and conformance has further steps: spec/22 §22.2 lists them in order. + +## Writing schemas + +Validators in many languages read the same schemas, which limits how the schemas are written. +The schemas use only the keywords listed in [spec/22-conformance.md](../spec/22-conformance.md#223-schemas). +Their patterns avoid `\d`, `\w`, `\s`, `\b` and lookbehind, so validators in every language read them alike. +The repository's own validator refuses a schema that uses any other keyword or those pattern tokens. +Optional properties are omitted rather than set to null, except where a schema says a property is nullable. diff --git a/schemas/anchor.schema.json b/schemas/anchor.schema.json new file mode 100644 index 0000000..5723974 --- /dev/null +++ b/schemas/anchor.schema.json @@ -0,0 +1,115 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/anchor.schema.json", + "title": "Anchor", + "description": "scienting-anchor/1: a pinned address with context; spec/06-anchors.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-anchor/1" + }, + "store": { + "$ref": "common.schema.json#/$defs/key" + }, + "doc": { + "$ref": "common.schema.json#/$defs/documentKey" + }, + "node": { + "$ref": "common.schema.json#/$defs/nodeRef" + }, + "kind": { + "$ref": "common.schema.json#/$defs/nodeKind" + }, + "own_hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "node_hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "span": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + }, + "minItems": 2, + "maxItems": 2 + }, + "quote": {}, + "context": {}, + "leaves": { + "type": "array", + "items": { + "type": "array", + "prefixItems": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "$ref": "common.schema.json#/$defs/hash" + } + ], + "minItems": 2, + "maxItems": 2 + }, + "minItems": 1 + }, + "rev": { + "type": "integer", + "minimum": 0 + }, + "keyed": { + "$ref": "common.schema.json#/$defs/hashing" + } + }, + "required": [ + "format", + "doc", + "node", + "own_hash", + "node_hash", + "rev" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "required": [ + "keyed" + ] + }, + "then": { + "properties": { + "quote": { + "$ref": "common.schema.json#/$defs/keyedQuote" + }, + "context": { + "$ref": "common.schema.json#/$defs/keyedContext" + } + } + }, + "else": { + "properties": { + "quote": { + "$ref": "common.schema.json#/$defs/quote" + }, + "context": { + "$ref": "common.schema.json#/$defs/cellContext" + } + } + } + }, + { + "if": { + "required": [ + "span" + ] + }, + "then": { + "required": [ + "quote" + ] + } + } + ] +} diff --git a/schemas/annotation.schema.json b/schemas/annotation.schema.json new file mode 100644 index 0000000..3aa0376 --- /dev/null +++ b/schemas/annotation.schema.json @@ -0,0 +1,743 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/annotation.schema.json", + "title": "Annotation", + "description": "One line of annotations.jsonl in scienting-layer/1: a W3C Web Annotation; spec/18-layers.md.", + "type": "object", + "properties": { + "@context": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 2 + }, + "id": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:annotation:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + }, + "type": { + "const": "Annotation" + }, + "layer": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:layer:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + }, + "motivation": { + "enum": [ + "commenting", + "describing", + "linking", + "questioning", + "assessing", + "tagging", + "classifying", + "identifying", + "editing", + "highlighting", + "bookmarking", + "replying", + "moderating" + ] + }, + "creator": { + "$ref": "common.schema.json#/$defs/agent" + }, + "created": { + "$ref": "common.schema.json#/$defs/time" + }, + "modified": { + "$ref": "common.schema.json#/$defs/time" + }, + "body": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "gloss" + }, + "audience": { + "enum": [ + "novice", + "student", + "expert" + ] + } + }, + "required": [ + "type", + "kind", + "value", + "audience" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "minLength": 1 + }, + "kind": { + "const": "claim-link" + }, + "pin": { + "type": "string", + "minLength": 1 + }, + "role": { + "enum": [ + "states", + "uses", + "disputes" + ] + } + }, + "required": [ + "type", + "kind", + "source", + "role" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "minLength": 1 + }, + "kind": { + "const": "symbol" + }, + "pin": { + "type": "string", + "minLength": 1 + }, + "symbol": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "type", + "kind", + "source" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "comment" + } + }, + "required": [ + "type", + "kind", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "caveat" + } + }, + "required": [ + "type", + "kind", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "question" + }, + "for": { + "enum": [ + "reader", + "group", + "authors" + ] + } + }, + "required": [ + "type", + "kind", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "exercise" + }, + "exercise": { + "$ref": "exercise.schema.json" + } + }, + "required": [ + "type", + "kind", + "value", + "exercise" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "citation-context" + }, + "reference": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "verdict": { + "enum": [ + "supports", + "partly", + "does-not", + "cannot-tell" + ] + }, + "reason": { + "enum": [ + "method", + "value", + "background", + "contrast", + "other" + ] + } + }, + "required": [ + "type", + "kind", + "value", + "reference" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "minLength": 1 + }, + "kind": { + "const": "prerequisite" + } + }, + "required": [ + "type", + "kind", + "source" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "minLength": 1 + }, + "kind": { + "const": "crosslink" + }, + "selector": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "const": "AnchorSelector" + }, + "anchor": { + "$ref": "anchor.schema.json" + } + }, + "required": [ + "type", + "anchor" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "type", + "kind", + "source", + "selector" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "translation" + } + }, + "required": [ + "type", + "kind", + "value", + "language" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "description" + }, + "role": { + "enum": [ + "alt", + "long" + ] + } + }, + "required": [ + "type", + "kind", + "value", + "role" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextualBody" + }, + "value": { + "type": "string", + "minLength": 1 + }, + "format": { + "enum": [ + "text/plain", + "text/markdown" + ] + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "kind": { + "const": "generated" + }, + "generator": { + "type": "object", + "properties": { + "model": { + "$ref": "common.schema.json#/$defs/model" + }, + "run": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "model", + "run" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "kind", + "value", + "generator" + ], + "additionalProperties": false + } + ] + }, + "target": { + "oneOf": [ + { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:doc:[a-z0-9][a-z0-9._-]*/[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(\\.[a-z0-9][a-z0-9-]*)*$" + }, + "selector": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "const": "AnchorSelector" + }, + "anchor": { + "$ref": "anchor.schema.json" + } + }, + "required": [ + "type", + "anchor" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextQuoteSelector" + }, + "exact": { + "type": "string", + "minLength": 1 + }, + "prefix": { + "type": "string" + }, + "suffix": { + "type": "string" + } + }, + "required": [ + "type", + "exact" + ], + "additionalProperties": false + } + ] + }, + "minItems": 1 + } + }, + "required": [ + "type", + "source", + "selector" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:annotation:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + } + }, + "required": [ + "type", + "source" + ], + "additionalProperties": false + } + ] + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:doc:[a-z0-9][a-z0-9._-]*/[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(\\.[a-z0-9][a-z0-9-]*)*$" + }, + "selector": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "const": "AnchorSelector" + }, + "anchor": { + "$ref": "anchor.schema.json" + } + }, + "required": [ + "type", + "anchor" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "TextQuoteSelector" + }, + "exact": { + "type": "string", + "minLength": 1 + }, + "prefix": { + "type": "string" + }, + "suffix": { + "type": "string" + } + }, + "required": [ + "type", + "exact" + ], + "additionalProperties": false + } + ] + }, + "minItems": 1 + } + }, + "required": [ + "type", + "source", + "selector" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "SpecificResource" + }, + "source": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:annotation:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + } + }, + "required": [ + "type", + "source" + ], + "additionalProperties": false + } + ] + }, + "minItems": 1 + } + ] + }, + "status": { + "enum": [ + "proposed", + "confirmed", + "rejected", + "withdrawn" + ] + }, + "receipt": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "rights_use": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "@context", + "id", + "type", + "layer", + "motivation", + "creator", + "created", + "body", + "target", + "status" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "status": { + "const": "confirmed" + } + } + }, + "then": { + "required": [ + "receipt" + ] + } + } + ] +} diff --git a/schemas/backend.schema.json b/schemas/backend.schema.json new file mode 100644 index 0000000..85cb5b6 --- /dev/null +++ b/schemas/backend.schema.json @@ -0,0 +1,164 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/backend.schema.json", + "title": "Backend declaration", + "description": "scienting-backend/1: a tool's code and weight licenses and their conditions; spec/14-rights.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-backend/1" + }, + "name": { + "$ref": "common.schema.json#/$defs/key" + }, + "version": { + "type": "string", + "minLength": 1 + }, + "stage": { + "enum": [ + "read", + "review", + "gloss", + "embed", + "digitize", + "other" + ] + }, + "processor": { + "$ref": "common.schema.json#/$defs/processor" + }, + "code_license": { + "$ref": "common.schema.json#/$defs/license" + }, + "weights": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "license": { + "$ref": "common.schema.json#/$defs/license" + }, + "url": { + "$ref": "common.schema.json#/$defs/url" + } + }, + "required": [ + "name", + "license" + ], + "additionalProperties": false + } + }, + "conditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "kind": { + "enum": [ + "revenue-cap", + "no-competition", + "purpose" + ] + }, + "usd": { + "type": "integer", + "minimum": 1 + }, + "vendor": { + "type": "string", + "minLength": 1 + }, + "allowed": { + "type": "array", + "items": { + "enum": [ + "research", + "personal", + "education", + "startup", + "commercial" + ] + }, + "minItems": 1 + }, + "source": { + "$ref": "common.schema.json#/$defs/url" + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "id", + "kind" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "kind": { + "const": "revenue-cap" + } + } + }, + "then": { + "required": [ + "usd" + ] + } + }, + { + "if": { + "properties": { + "kind": { + "const": "no-competition" + } + } + }, + "then": { + "required": [ + "vendor" + ] + } + }, + { + "if": { + "properties": { + "kind": { + "const": "purpose" + } + } + }, + "then": { + "required": [ + "allowed" + ] + } + } + ] + } + } + }, + "required": [ + "format", + "name", + "version", + "stage", + "processor", + "code_license", + "weights", + "conditions" + ], + "additionalProperties": false +} diff --git a/schemas/checklist.schema.json b/schemas/checklist.schema.json new file mode 100644 index 0000000..bc13370 --- /dev/null +++ b/schemas/checklist.schema.json @@ -0,0 +1,151 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/checklist.schema.json", + "title": "Conformance checklist", + "description": "scienting-checklist/1: a check of an export against a named standard, covered by a receipt; spec/08-fidelity.md §8.11.", + "type": "object", + "properties": { + "format": { + "const": "scienting-checklist/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "doc": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + }, + "rev": { + "type": "integer", + "minimum": 0 + }, + "standard": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "level": { + "type": "string", + "minLength": 1 + }, + "url": { + "$ref": "common.schema.json#/$defs/url" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "export": { + "type": "object", + "properties": { + "kind": { + "enum": [ + "html", + "pdf", + "epub", + "other" + ] + }, + "sha256": { + "$ref": "common.schema.json#/$defs/hash" + }, + "size": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "kind", + "sha256" + ], + "additionalProperties": false + }, + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "criterion": { + "type": "string", + "minLength": 1 + }, + "result": { + "enum": [ + "pass", + "fail", + "not-applicable" + ] + }, + "method": { + "enum": [ + "manual", + "automated" + ] + }, + "tool": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "version": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name", + "version" + ], + "additionalProperties": false + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "criterion", + "result", + "method" + ], + "additionalProperties": false, + "if": { + "properties": { + "method": { + "const": "automated" + } + } + }, + "then": { + "required": [ + "tool" + ] + } + }, + "minItems": 1 + }, + "by": { + "$ref": "common.schema.json#/$defs/key" + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + } + }, + "required": [ + "format", + "id", + "doc", + "rev", + "standard", + "export", + "items", + "by", + "at" + ], + "additionalProperties": false +} diff --git a/schemas/checkpoint.schema.json b/schemas/checkpoint.schema.json new file mode 100644 index 0000000..8bf6c17 --- /dev/null +++ b/schemas/checkpoint.schema.json @@ -0,0 +1,62 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/checkpoint.schema.json", + "title": "Log checkpoint", + "description": "scienting-checkpoint/1: a signed checkpoint of a team's transparency log, as the parsed form of its signed note; spec/23-log.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-checkpoint/1" + }, + "origin": { + "type": "string", + "pattern": "^[^\\n]+$", + "minLength": 1 + }, + "size": { + "type": "integer", + "minimum": 0 + }, + "root": { + "$ref": "common.schema.json#/$defs/hash" + }, + "signatures": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "$ref": "common.schema.json#/$defs/key" + }, + "key_hash": { + "type": "string", + "pattern": "^[0-9a-f]{8}$" + }, + "value": { + "$ref": "common.schema.json#/$defs/base64" + } + }, + "required": [ + "name", + "key_hash", + "value" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "format", + "origin", + "size", + "root", + "signatures", + "note" + ], + "additionalProperties": false +} diff --git a/schemas/common.schema.json b/schemas/common.schema.json new file mode 100644 index 0000000..6defcd0 --- /dev/null +++ b/schemas/common.schema.json @@ -0,0 +1,617 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/common.schema.json", + "title": "Shared definitions", + "description": "Definitions every scienting schema shares; spec/01-conventions.md.", + "$defs": { + "hash": { + "type": "string", + "pattern": "^[0-9a-f]{64}$", + "description": "SHA-256 or HMAC-SHA-256, 64 lowercase hex digits." + }, + "hash6": { + "type": "string", + "pattern": "^[0-9a-f]{6}$" + }, + "nodeId": { + "type": "string", + "pattern": "^[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6}$", + "description": "Seven lowercase Crockford base32 characters, the first a letter." + }, + "recordId": { + "type": "string", + "pattern": "^[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + }, + "key": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9._-]*$", + "maxLength": 128, + "description": "A store, project or source key, or a legacy document key kept as an alias." + }, + "workKey": { + "type": "string", + "pattern": "^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}$", + "maxLength": 128, + "description": "A Scholar-style part, a hyphen and the hash of the work's identity (spec/02 §2.4)." + }, + "documentKey": { + "type": "string", + "pattern": "^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(\\.[a-z0-9][a-z0-9-]*)*$", + "maxLength": 128, + "description": "A work key, with a dotted suffix for anything other than the version of record." + }, + "alias": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9._-]*[._-][a-z0-9._-]*$", + "maxLength": 128, + "description": "A legacy ID; it always contains a separator, so it never looks like a node ID." + }, + "nodeRef": { + "anyOf": [ + { + "$ref": "#/$defs/nodeId" + }, + { + "$ref": "#/$defs/alias" + } + ] + }, + "qualifiedKey": { + "type": "string", + "pattern": "^([a-z0-9][a-z0-9._-]*/)?[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(\\.[a-z0-9][a-z0-9-]*)*$", + "maxLength": 257, + "description": "A document key, optionally qualified by its store." + }, + "datasetId": { + "type": "string", + "pattern": "^ds-[a-z0-9][a-z0-9._-]*$", + "maxLength": 128 + }, + "address": { + "type": "string", + "pattern": "^([a-z0-9][a-z0-9._-]*/)?[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(\\.[a-z0-9][a-z0-9-]*)*#[a-z0-9][a-z0-9._-]*(@[0-9a-f]{6})?(\\[(0|[1-9][0-9]*):(0|[1-9][0-9]*)\\])?$" + }, + "time": { + "type": "string", + "pattern": "^[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z$" + }, + "date": { + "type": "string", + "pattern": "^[0-9]{4}(-[0-1][0-9](-[0-3][0-9])?)?$" + }, + "decimal": { + "type": "string", + "pattern": "^-?(0|[1-9][0-9]*)(\\.[0-9]+)?$", + "description": "A decimal that carries meaning, as a string." + }, + "level": { + "enum": [ + "F0", + "F1", + "F2", + "F3" + ] + }, + "receiptLevel": { + "enum": [ + "F1", + "F2", + "F3" + ] + }, + "nodeKind": { + "enum": [ + "document", + "front", + "title", + "authors", + "abstract", + "keywords", + "notes", + "section", + "heading", + "paragraph", + "sentence", + "equation", + "equation-line", + "figure", + "panel", + "caption", + "figure-note", + "table", + "table-head", + "table-body", + "table-note", + "row", + "cell", + "list", + "item", + "quote", + "code", + "algorithm", + "theorem", + "footnote", + "back", + "acknowledgments", + "references", + "reference", + "appendix" + ] + }, + "box": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 4, + "maxItems": 4, + "description": "[x0, y0, x1, y1] in PDF points, origin top left after rotation." + }, + "size": { + "type": "array", + "items": { + "type": "number", + "exclusiveMinimum": 0 + }, + "minItems": 2, + "maxItems": 2 + }, + "url": { + "type": "string", + "pattern": "^[a-z][a-z0-9+.-]*:[^ ]+$" + }, + "language": { + "type": "string", + "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{1,8})*$" + }, + "spdx": { + "type": "string", + "pattern": "^[A-Za-z0-9.+-]+( (AND|OR|WITH) [A-Za-z0-9.+-]+)*$" + }, + "license": { + "type": "object", + "properties": { + "spdx": { + "$ref": "#/$defs/spdx" + }, + "text": { + "type": "string", + "minLength": 1 + }, + "url": { + "$ref": "#/$defs/url" + } + }, + "additionalProperties": false, + "minProperties": 1 + }, + "tri": { + "enum": [ + true, + false, + "unknown" + ] + }, + "base64": { + "type": "string", + "pattern": "^[A-Za-z0-9+/]+={0,2}$" + }, + "processor": { + "enum": [ + "local", + "tenancy", + "outside-no-retention", + "outside" + ] + }, + "basis": { + "enum": [ + "open-license", + "publisher-tdm", + "collective-license", + "subscription", + "own-work", + "permission", + "unknown" + ] + }, + "signature": { + "type": "object", + "properties": { + "scheme": { + "enum": [ + "ed25519", + "ssh", + "gpg", + "sigstore", + "cose", + "ml-dsa-65" + ] + }, + "key": { + "$ref": "#/$defs/key" + }, + "value": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "scheme", + "key", + "value" + ], + "additionalProperties": false + }, + "evidence": { + "type": "object", + "properties": { + "kind": { + "enum": [ + "crop", + "witness", + "source-file", + "person" + ] + }, + "sha256": { + "$ref": "#/$defs/hash" + }, + "node": { + "$ref": "#/$defs/nodeId" + }, + "page_fp": { + "$ref": "#/$defs/hash" + }, + "box": { + "$ref": "#/$defs/box" + }, + "by": { + "$ref": "#/$defs/key" + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "kind": { + "const": "person" + } + } + }, + "then": { + "required": [ + "by" + ] + }, + "else": { + "required": [ + "sha256" + ] + } + } + ] + }, + "author": { + "oneOf": [ + { + "type": "object", + "properties": { + "key": { + "$ref": "#/$defs/key" + } + }, + "required": [ + "key" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "model": { + "$ref": "#/$defs/model" + }, + "run": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "model", + "run" + ], + "additionalProperties": false + } + ] + }, + "hashAlgorithm": { + "enum": [ + "sha-256" + ], + "description": "The hash function every value of a package uses; the only value so far (spec/01 §1.3)." + }, + "hashing": { + "oneOf": [ + { + "type": "object", + "properties": { + "scheme": { + "const": "plain" + }, + "algorithm": { + "$ref": "#/$defs/hashAlgorithm" + } + }, + "required": [ + "scheme" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "scheme": { + "const": "hmac-team" + }, + "algorithm": { + "$ref": "#/$defs/hashAlgorithm" + }, + "key_id": { + "type": "string", + "pattern": "^[0-9a-f]{16}$" + } + }, + "required": [ + "scheme", + "key_id" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "scheme": { + "const": "hkdf-pages" + }, + "algorithm": { + "$ref": "#/$defs/hashAlgorithm" + }, + "context": { + "type": "string", + "minLength": 1 + }, + "pages": { + "type": "array", + "items": { + "$ref": "#/$defs/hash" + }, + "minItems": 1 + } + }, + "required": [ + "scheme", + "context", + "pages" + ], + "additionalProperties": false + } + ] + }, + "model": { + "type": "object", + "description": "A model that proposed something: enough to name the weights and the instructions it ran with (spec/11 §11.2).", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "provider": { + "type": "string", + "minLength": 1 + }, + "version": { + "type": "string", + "minLength": 1 + }, + "weights": { + "$ref": "#/$defs/hash" + }, + "prompt": { + "$ref": "#/$defs/hash" + }, + "parameters": { + "$ref": "#/$defs/hash" + }, + "processor": { + "$ref": "#/$defs/processor" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "quote": { + "type": "object", + "properties": { + "exact": { + "type": "string", + "maxLength": 200 + }, + "exact_hash": { + "$ref": "#/$defs/hash" + }, + "length": { + "type": "integer", + "minimum": 201 + }, + "prefix": { + "type": "string", + "minLength": 1, + "maxLength": 32 + }, + "suffix": { + "type": "string", + "minLength": 1, + "maxLength": 32 + } + }, + "required": [], + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "exact" + ], + "not": { + "anyOf": [ + { + "required": [ + "exact_hash" + ] + }, + { + "required": [ + "length" + ] + } + ] + } + }, + { + "required": [ + "exact_hash", + "length" + ], + "not": { + "required": [ + "exact" + ] + } + } + ] + }, + "keyedQuote": { + "type": "object", + "properties": { + "mac": { + "$ref": "#/$defs/hash" + }, + "length": { + "type": "integer", + "minimum": 0 + }, + "prefix_mac": { + "$ref": "#/$defs/hash" + }, + "suffix_mac": { + "$ref": "#/$defs/hash" + } + }, + "required": [ + "mac", + "length" + ], + "additionalProperties": false + }, + "cellContext": { + "type": "object", + "properties": { + "table_label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "row_path": { + "type": "array", + "items": { + "type": "string" + } + }, + "column_path": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "table_label", + "row_path", + "column_path" + ], + "additionalProperties": false + }, + "keyedContext": { + "type": "object", + "properties": { + "table_label_mac": { + "anyOf": [ + { + "$ref": "#/$defs/hash" + }, + { + "type": "null" + } + ] + }, + "row_path_mac": { + "type": "array", + "items": { + "$ref": "#/$defs/hash" + } + }, + "column_path_mac": { + "type": "array", + "items": { + "$ref": "#/$defs/hash" + } + } + }, + "required": [ + "table_label_mac", + "row_path_mac", + "column_path_mac" + ], + "additionalProperties": false + }, + "agent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:(key|person|software):[^ ]+$" + }, + "type": { + "enum": [ + "Person", + "Software" + ] + }, + "name": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + } + } +} diff --git a/schemas/correction.schema.json b/schemas/correction.schema.json new file mode 100644 index 0000000..a54486d --- /dev/null +++ b/schemas/correction.schema.json @@ -0,0 +1,376 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/correction.schema.json", + "title": "Correction", + "description": "scienting-correction/1: a line of corrections.jsonl, or a proposal; spec/11-corrections.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-correction/1" + }, + "index": { + "type": "integer", + "minimum": 1 + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "op": { + "enum": [ + "replace", + "insert", + "delete", + "split", + "merge", + "move", + "reclassify", + "relabel", + "set" + ] + }, + "target": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "find": { + "type": "string", + "minLength": 1 + }, + "replace": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "runs.schema.json" + } + ] + }, + "run": { + "type": "integer", + "minimum": 0 + }, + "offset": { + "type": "integer", + "minimum": 0 + }, + "text": { + "type": "string", + "minLength": 1 + }, + "parent": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "node": { + "type": "object", + "description": "A node subtree to insert: kind, label, attrs, content and children; equation runs name a child by position." + }, + "with": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "joiner": { + "type": "string" + }, + "kind": { + "$ref": "common.schema.json#/$defs/nodeKind" + }, + "label": { + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ] + }, + "attr": { + "enum": [ + "level", + "columns", + "column", + "rowspan", + "colspan", + "role", + "header_path", + "ordered", + "marker", + "variant" + ] + }, + "value": {}, + "evidence": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/evidence" + }, + "minItems": 1 + }, + "author": { + "$ref": "common.schema.json#/$defs/author" + }, + "reason": { + "type": "string", + "minLength": 1 + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + }, + "before": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/hash" + }, + { + "type": "null" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + } + }, + { + "type": "null" + } + ] + }, + "to_path": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + } + }, + "touched": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "uniqueItems": true + }, + "created": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "minItems": 1 + }, + "retired": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "minItems": 1 + }, + "from": {}, + "status": { + "enum": [ + "proposed" + ] + }, + "after": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/hash" + }, + { + "type": "null" + } + ] + }, + "place_after": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "format", + "op", + "evidence", + "author", + "reason", + "at" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "op": { + "const": "replace" + } + } + }, + "then": { + "required": [ + "target", + "find", + "replace" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "delete" + } + } + }, + "then": { + "required": [ + "target" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "split" + } + } + }, + "then": { + "required": [ + "target", + "offset" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "merge" + } + } + }, + "then": { + "required": [ + "target", + "with" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "move" + } + } + }, + "then": { + "required": [ + "target", + "parent" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "reclassify" + } + } + }, + "then": { + "required": [ + "target", + "kind" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "relabel" + } + } + }, + "then": { + "required": [ + "target", + "label" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "set" + } + } + }, + "then": { + "required": [ + "target", + "attr", + "value" + ] + } + }, + { + "if": { + "properties": { + "op": { + "const": "insert" + } + } + }, + "then": { + "oneOf": [ + { + "required": [ + "parent", + "node" + ] + }, + { + "required": [ + "target", + "run", + "offset", + "text" + ] + } + ] + } + }, + { + "if": { + "required": [ + "index" + ] + }, + "then": { + "required": [ + "id", + "before", + "after", + "path", + "touched" + ] + }, + "else": { + "required": [ + "status" + ] + } + } + ] +} diff --git a/schemas/dataset.schema.json b/schemas/dataset.schema.json new file mode 100644 index 0000000..36f7392 --- /dev/null +++ b/schemas/dataset.schema.json @@ -0,0 +1,365 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/dataset.schema.json", + "title": "Dataset", + "description": "datapackage.json of scienting-dataset/1: a Frictionless Data Package with units, uncertainty and origin; spec/15-datasets.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-dataset/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/datasetId" + }, + "name": { + "$ref": "common.schema.json#/$defs/key" + }, + "title": { + "type": "string", + "minLength": 1 + }, + "licenses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "path": { + "$ref": "common.schema.json#/$defs/url" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "resources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "$ref": "common.schema.json#/$defs/key" + }, + "path": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9._-]*\\.(csv|parquet)$" + }, + "format": { + "enum": [ + "csv", + "parquet" + ] + }, + "mediatype": { + "type": "string", + "minLength": 1 + }, + "encoding": { + "const": "utf-8" + }, + "schema": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$" + }, + "type": { + "enum": [ + "string", + "number", + "integer", + "boolean", + "date", + "datetime", + "any" + ] + }, + "title": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 1 + }, + "unit": { + "type": "string", + "minLength": 1 + }, + "uncertainty": { + "type": "object", + "properties": { + "field": { + "type": "string", + "minLength": 1 + }, + "kind": { + "enum": [ + "sd", + "se", + "resolution", + "unknown" + ] + } + }, + "required": [ + "kind" + ], + "additionalProperties": false + }, + "constraints": { + "type": "object" + } + }, + "required": [ + "name", + "type" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "type": { + "const": "number" + } + } + }, + "then": { + "required": [ + "unit" + ] + } + } + ] + }, + "minItems": 1 + }, + "primaryKey": { + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 1 + } + ] + } + }, + "required": [ + "fields" + ], + "additionalProperties": false + }, + "origin": { + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "const": "reported" + }, + "anchors": { + "const": "anchors.jsonl" + } + }, + "required": [ + "kind", + "anchors" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "digitized" + }, + "digitization": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "anchors": { + "const": "anchors.jsonl" + } + }, + "required": [ + "kind", + "digitization" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "computed" + }, + "claim": { + "type": "string", + "minLength": 1 + }, + "pin": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "claim", + "pin" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "measured" + }, + "provenance": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "provenance" + ], + "additionalProperties": false + } + ] + }, + "origin_field": { + "type": "string", + "minLength": 1 + }, + "origins": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "const": "reported" + }, + "anchors": { + "const": "anchors.jsonl" + } + }, + "required": [ + "kind", + "anchors" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "digitized" + }, + "digitization": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "anchors": { + "const": "anchors.jsonl" + } + }, + "required": [ + "kind", + "digitization" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "computed" + }, + "claim": { + "type": "string", + "minLength": 1 + }, + "pin": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "claim", + "pin" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "measured" + }, + "provenance": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "provenance" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "name", + "path", + "schema" + ], + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "origin" + ] + }, + { + "required": [ + "origin_field", + "origins" + ] + } + ] + }, + "minItems": 1 + } + }, + "required": [ + "format", + "id", + "name", + "resources" + ], + "additionalProperties": false +} diff --git a/schemas/digitization.schema.json b/schemas/digitization.schema.json new file mode 100644 index 0000000..b107563 --- /dev/null +++ b/schemas/digitization.schema.json @@ -0,0 +1,368 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/digitization.schema.json", + "title": "Digitization", + "description": "scienting-digitization/1: how values were read off a figure panel; spec/16-digitization.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-digitization/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "doc": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + }, + "target": { + "type": "object", + "properties": { + "anchor": { + "$ref": "anchor.schema.json" + }, + "page_fp": { + "$ref": "common.schema.json#/$defs/hash" + }, + "region": { + "$ref": "common.schema.json#/$defs/box" + }, + "witness": { + "$ref": "common.schema.json#/$defs/hash" + }, + "image": { + "$ref": "common.schema.json#/$defs/hash" + } + }, + "required": [ + "anchor", + "region" + ], + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "page_fp", + "witness" + ], + "not": { + "required": [ + "image" + ] + } + }, + { + "required": [ + "image" + ], + "not": { + "required": [ + "page_fp" + ] + } + } + ] + }, + "axes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "enum": [ + "x", + "y", + "y2", + "x2" + ] + }, + "scale": { + "enum": [ + "linear", + "log", + "reciprocal", + "date" + ] + }, + "unit": { + "type": "string", + "minLength": 1 + }, + "calibration": { + "type": "array", + "items": { + "type": "object", + "properties": { + "at": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "value": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "at", + "value" + ], + "additionalProperties": false + }, + "minItems": 2 + }, + "check": { + "type": "object", + "properties": { + "at": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "value": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "at", + "value" + ], + "additionalProperties": false + }, + "label": { + "type": "object", + "properties": { + "panel": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "figure_text": { + "$ref": "common.schema.json#/$defs/nodeId" + } + }, + "required": [ + "panel", + "figure_text" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "scale", + "calibration" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "series": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "legend": { + "type": "string", + "minLength": 1 + }, + "mark": { + "type": "object", + "properties": { + "color": { + "type": "string", + "pattern": "^#[0-9a-f]{6}$" + }, + "marker": { + "type": "string", + "minLength": 1 + }, + "line": { + "type": "string", + "minLength": 1 + } + }, + "required": [], + "additionalProperties": false + }, + "kind": { + "enum": [ + "points", + "line", + "bars", + "error-bars", + "region" + ] + }, + "values": { + "type": "array", + "items": { + "type": "object", + "properties": { + "at": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "value": { + "type": "object", + "properties": { + "x": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "y": { + "$ref": "common.schema.json#/$defs/decimal" + } + }, + "required": [ + "x", + "y" + ], + "additionalProperties": false + }, + "uncertainty": { + "type": "object", + "properties": { + "x": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "y": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "resolution": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "marker": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "calibration": { + "$ref": "common.schema.json#/$defs/decimal" + } + }, + "required": [ + "x", + "y" + ], + "additionalProperties": false + } + }, + "required": [ + "at", + "value", + "uncertainty" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "id", + "kind", + "values" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "method": { + "type": "object", + "properties": { + "kind": { + "enum": [ + "manual", + "traced", + "proposed" + ] + }, + "tool": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "version": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name", + "version" + ], + "additionalProperties": false + }, + "model": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "tool" + ], + "additionalProperties": false + }, + "verification": { + "type": "object", + "properties": { + "image": { + "$ref": "common.schema.json#/$defs/hash" + }, + "residual": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "max_residual": { + "$ref": "common.schema.json#/$defs/decimal" + } + }, + "required": [ + "image", + "residual", + "max_residual" + ], + "additionalProperties": false + }, + "confirmation": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/recordId" + }, + { + "type": "null" + } + ] + }, + "dataset": { + "$ref": "common.schema.json#/$defs/datasetId" + }, + "rev": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "format", + "id", + "doc", + "target", + "axes", + "series", + "method", + "verification", + "confirmation", + "rev" + ], + "additionalProperties": false +} diff --git a/schemas/document.schema.json b/schemas/document.schema.json new file mode 100644 index 0000000..e03bae6 --- /dev/null +++ b/schemas/document.schema.json @@ -0,0 +1,232 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/document.schema.json", + "title": "Document", + "description": "document.json of a scienting-doc/1 package; spec/02-model.md and spec/12-package.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-doc/1" + }, + "key": { + "$ref": "common.schema.json#/$defs/documentKey" + }, + "store": { + "$ref": "common.schema.json#/$defs/key" + }, + "history": { + "$ref": "common.schema.json#/$defs/hash" + }, + "aliases": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/key" + }, + "minItems": 1, + "uniqueItems": true + }, + "kind": { + "enum": [ + "article", + "supplement", + "chapter", + "book", + "thesis", + "report", + "draft", + "course-material", + "other" + ] + }, + "work": { + "type": "object", + "properties": { + "key": { + "$ref": "common.schema.json#/$defs/workKey" + }, + "same_as": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(doi|arxiv|isbn|pmid|pmcid|openalex|url|lode):[^ ]+$" + }, + "uniqueItems": true + } + }, + "required": [ + "key", + "same_as" + ], + "additionalProperties": false + }, + "version": { + "type": "object", + "properties": { + "type": { + "enum": [ + "preprint", + "submitted", + "accepted", + "version-of-record", + "erratum", + "retraction", + "supplement", + "draft", + "other" + ] + }, + "seq": { + "type": "integer", + "minimum": 1 + }, + "date": { + "$ref": "common.schema.json#/$defs/date" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "relations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "enum": [ + "supplement-of", + "part-of", + "version-of", + "erratum-of", + "retraction-of", + "translation-of" + ] + }, + "target": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + } + }, + "required": [ + "type", + "target" + ], + "additionalProperties": false + } + }, + "meta": { + "type": "object", + "description": "A CSL-JSON item for the version." + }, + "language": { + "$ref": "common.schema.json#/$defs/language" + }, + "license": { + "$ref": "common.schema.json#/$defs/license" + }, + "policy": { + "enum": [ + "full", + "checks-only" + ] + }, + "hashing": { + "$ref": "common.schema.json#/$defs/hashing" + }, + "root": { + "$ref": "common.schema.json#/$defs/hash" + }, + "meta_hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "rev": { + "type": "integer", + "minimum": 0 + }, + "counts": { + "type": "object", + "properties": { + "nodes": { + "type": "integer", + "minimum": 1 + }, + "leaves": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "nodes", + "leaves" + ], + "additionalProperties": false + }, + "fidelity": { + "type": "object", + "properties": { + "lowest": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/level" + }, + { + "type": "null" + } + ] + }, + "counts": { + "type": "object", + "properties": { + "F0": { + "type": "integer", + "minimum": 0 + }, + "F1": { + "type": "integer", + "minimum": 0 + }, + "F2": { + "type": "integer", + "minimum": 0 + }, + "F3": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "F0", + "F1", + "F2", + "F3" + ], + "additionalProperties": false + } + }, + "required": [ + "lowest", + "counts" + ], + "additionalProperties": false + } + }, + "required": [ + "format", + "key", + "kind", + "work", + "version", + "relations", + "meta", + "language", + "policy", + "hashing", + "root", + "meta_hash", + "history", + "rev", + "counts", + "fidelity" + ], + "additionalProperties": false +} diff --git a/schemas/draft-ids.schema.json b/schemas/draft-ids.schema.json new file mode 100644 index 0000000..3ca8ead --- /dev/null +++ b/schemas/draft-ids.schema.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/draft-ids.schema.json", + "title": "Draft sentence IDs", + "description": "One line of a Typst project's ids.jsonl: scienting-draft-ids/1; spec/21-drafts.md.", + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "text_hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "section": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "type": "null" + } + ] + }, + "ord": { + "type": "integer", + "minimum": 0 + }, + "pinned": { + "$ref": "common.schema.json#/$defs/key" + } + }, + "required": [ + "id", + "text_hash", + "section", + "ord" + ], + "additionalProperties": false +} diff --git a/schemas/exercise.schema.json b/schemas/exercise.schema.json new file mode 100644 index 0000000..1e60408 --- /dev/null +++ b/schemas/exercise.schema.json @@ -0,0 +1,351 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/exercise.schema.json", + "title": "Exercise", + "description": "scienting-exercise/1: the body of an exercise annotation; spec/19-exercises.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-exercise/1" + }, + "exercise": { + "enum": [ + "anchor", + "check", + "trace", + "reproduce", + "verify" + ] + }, + "prompt": { + "type": "string", + "minLength": 1 + }, + "summary": { + "type": "string", + "minLength": 1 + }, + "key": { + "type": "object", + "properties": { + "elements": { + "type": "array", + "items": { + "type": "object", + "properties": { + "anchors": { + "type": "array", + "items": { + "$ref": "anchor.schema.json" + }, + "minItems": 1 + }, + "points": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "feedback": { + "type": "object", + "properties": { + "hit": { + "type": "string" + }, + "miss": { + "type": "string" + } + }, + "required": [], + "additionalProperties": false + } + }, + "required": [ + "anchors", + "points" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "verdict": { + "type": "object", + "properties": { + "value": { + "enum": [ + "supports", + "partly", + "does-not", + "cannot-tell" + ] + }, + "points": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "feedback": { + "type": "object", + "properties": { + "hit": { + "type": "string" + }, + "miss": { + "type": "string" + } + }, + "required": [], + "additionalProperties": false + } + }, + "required": [ + "value", + "points" + ], + "additionalProperties": false + }, + "chain": { + "type": "array", + "items": { + "type": "object", + "properties": { + "anchors": { + "type": "array", + "items": { + "$ref": "anchor.schema.json" + }, + "minItems": 1 + }, + "points": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "feedback": { + "type": "object", + "properties": { + "hit": { + "type": "string" + }, + "miss": { + "type": "string" + } + }, + "required": [], + "additionalProperties": false + } + }, + "required": [ + "anchors", + "points" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "value": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "tolerance": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "unit": { + "type": "string", + "minLength": 1 + }, + "digitization": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "points": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "feedback": { + "type": "object", + "properties": { + "hit": { + "type": "string" + }, + "miss": { + "type": "string" + } + }, + "required": [], + "additionalProperties": false + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "anchors": { + "type": "array", + "items": { + "$ref": "anchor.schema.json" + }, + "minItems": 1 + }, + "verdict": { + "enum": [ + "supports", + "partly", + "does-not", + "cannot-tell" + ] + }, + "points": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "feedback": { + "type": "object", + "properties": { + "hit": { + "type": "string" + }, + "miss": { + "type": "string" + } + }, + "required": [], + "additionalProperties": false + } + }, + "required": [ + "anchors", + "verdict", + "points" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [], + "additionalProperties": false + }, + "rule": { + "type": "object", + "properties": { + "match": { + "enum": [ + "same-node", + "overlap", + "chain" + ] + }, + "min_overlap": { + "$ref": "common.schema.json#/$defs/decimal" + } + }, + "required": [ + "match" + ], + "additionalProperties": false + } + }, + "required": [ + "format", + "exercise", + "prompt", + "key", + "rule" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "exercise": { + "const": "anchor" + } + } + }, + "then": { + "properties": { + "key": { + "required": [ + "elements" + ] + } + } + } + }, + { + "if": { + "properties": { + "exercise": { + "const": "check" + } + } + }, + "then": { + "properties": { + "key": { + "required": [ + "elements", + "verdict" + ] + } + } + } + }, + { + "if": { + "properties": { + "exercise": { + "const": "trace" + } + } + }, + "then": { + "properties": { + "key": { + "required": [ + "chain" + ] + }, + "rule": { + "properties": { + "match": { + "const": "chain" + } + } + } + } + } + }, + { + "if": { + "properties": { + "exercise": { + "const": "reproduce" + } + } + }, + "then": { + "properties": { + "key": { + "required": [ + "value", + "tolerance", + "points" + ] + } + } + } + }, + { + "if": { + "properties": { + "exercise": { + "const": "verify" + } + } + }, + "then": { + "required": [ + "summary" + ], + "properties": { + "key": { + "required": [ + "errors" + ] + } + } + } + } + ] +} diff --git a/schemas/grade.schema.json b/schemas/grade.schema.json new file mode 100644 index 0000000..d548685 --- /dev/null +++ b/schemas/grade.schema.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/grade.schema.json", + "title": "Grade", + "description": "scienting-grade/1: the grader's result for one submission; spec/19-exercises.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-grade/1" + }, + "submission": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "exercise": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:annotation:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + }, + "score": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "max": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "element": { + "type": "string", + "minLength": 1 + }, + "points": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "max": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "feedback": { + "type": "string" + } + }, + "required": [ + "element", + "points", + "max", + "feedback" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "format", + "submission", + "exercise", + "score", + "max", + "items" + ], + "additionalProperties": false +} diff --git a/schemas/id-entry.schema.json b/schemas/id-entry.schema.json new file mode 100644 index 0000000..cca2c96 --- /dev/null +++ b/schemas/id-entry.schema.json @@ -0,0 +1,87 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/id-entry.schema.json", + "title": "ID table entry", + "description": "One line of ids.jsonl; spec/04-identity.md.", + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/nodeRef" + }, + "kind": { + "enum": [ + "retired", + "alias" + ] + }, + "successor": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "type": "null" + } + ] + }, + "node_kind": { + "$ref": "common.schema.json#/$defs/nodeKind" + }, + "rev": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "kind", + "successor" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "kind": { + "const": "retired" + } + } + }, + "then": { + "required": [ + "node_kind", + "rev" + ], + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/nodeId" + } + } + }, + "else": { + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/alias" + }, + "successor": { + "$ref": "common.schema.json#/$defs/nodeId" + } + }, + "not": { + "anyOf": [ + { + "required": [ + "rev" + ] + }, + { + "required": [ + "node_kind" + ] + } + ] + } + } + } + ] +} diff --git a/schemas/layer.schema.json b/schemas/layer.schema.json new file mode 100644 index 0000000..c5b0fe0 --- /dev/null +++ b/schemas/layer.schema.json @@ -0,0 +1,89 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/layer.schema.json", + "title": "Layer", + "description": "layer.json of scienting-layer/1: a W3C AnnotationCollection; spec/18-layers.md.", + "type": "object", + "properties": { + "@context": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 2 + }, + "format": { + "const": "scienting-layer/1" + }, + "id": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:layer:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + }, + "type": { + "const": "AnnotationCollection" + }, + "label": { + "type": "string", + "minLength": 1 + }, + "purpose": { + "type": "string", + "minLength": 1 + }, + "audience": { + "enum": [ + "novice", + "student", + "expert", + "mixed" + ] + }, + "visibility": { + "enum": [ + "private", + "team", + "public" + ] + }, + "license": { + "$ref": "common.schema.json#/$defs/license" + }, + "creator": { + "$ref": "common.schema.json#/$defs/agent" + }, + "created": { + "$ref": "common.schema.json#/$defs/time" + }, + "project": { + "$ref": "common.schema.json#/$defs/key" + }, + "docs": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + }, + "minItems": 1, + "uniqueItems": true + }, + "total": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "@context", + "format", + "id", + "type", + "label", + "purpose", + "visibility", + "license", + "creator", + "created", + "docs", + "total" + ], + "additionalProperties": false +} diff --git a/schemas/location.schema.json b/schemas/location.schema.json new file mode 100644 index 0000000..a270218 --- /dev/null +++ b/schemas/location.schema.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/location.schema.json", + "title": "Location", + "description": "One line of locations.jsonl; spec/07-geometry.md.", + "type": "object", + "properties": { + "node": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "page_fp": { + "$ref": "common.schema.json#/$defs/hash" + }, + "page": { + "type": "integer", + "minimum": 1 + }, + "page_label": { + "type": "string", + "minLength": 1 + }, + "boxes": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/box" + }, + "minItems": 1 + }, + "approx": { + "const": true + } + }, + "required": [ + "node", + "page_fp", + "page", + "boxes" + ], + "additionalProperties": false +} diff --git a/schemas/log-entry.schema.json b/schemas/log-entry.schema.json new file mode 100644 index 0000000..cb2bfbc --- /dev/null +++ b/schemas/log-entry.schema.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/log-entry.schema.json", + "title": "Log entry", + "description": "scienting-log-entry/1: one item of a team's transparency log, [kind, id, hash]: the kind of record, its ID (or the store for a roster) and its record hash; spec/23-log.md.", + "type": "array", + "prefixItems": [ + { + "enum": [ + "receipt", + "revocation", + "roster" + ] + }, + { + "$ref": "common.schema.json#/$defs/key" + }, + { + "$ref": "common.schema.json#/$defs/hash" + } + ], + "minItems": 3, + "maxItems": 3 +} diff --git a/schemas/manifest.schema.json b/schemas/manifest.schema.json new file mode 100644 index 0000000..c54f8e8 --- /dev/null +++ b/schemas/manifest.schema.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/manifest.schema.json", + "title": "Package manifest", + "description": "MANIFEST.json, scienting-package/1; spec/12-package.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-package/1" + }, + "doc": { + "const": "scienting-doc/1" + }, + "key": { + "$ref": "common.schema.json#/$defs/documentKey" + }, + "files": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "minLength": 1, + "maxLength": 512 + }, + "sha256": { + "$ref": "common.schema.json#/$defs/hash" + }, + "size": { + "type": "integer", + "minimum": 0 + }, + "present": { + "const": false + }, + "media_type": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "path", + "sha256", + "size" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "format", + "doc", + "key", + "files" + ], + "additionalProperties": false +} diff --git a/schemas/mathml.schema.json b/schemas/mathml.schema.json new file mode 100644 index 0000000..215c172 --- /dev/null +++ b/schemas/mathml.schema.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/mathml.schema.json", + "title": "Derived MathML", + "description": "One line of derived/mathml.jsonl: MathML made by a pinned tool; never authoritative; spec/12-package.md.", + "type": "object", + "properties": { + "node": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "run": { + "anyOf": [ + { + "type": "integer", + "minimum": 0 + }, + { + "type": "null" + } + ] + }, + "tool": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "version": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name", + "version" + ], + "additionalProperties": false + }, + "mathml": { + "type": "string", + "pattern": "^]" + } + }, + "required": [ + "node", + "run", + "tool", + "mathml" + ], + "additionalProperties": false +} diff --git a/schemas/node.schema.json b/schemas/node.schema.json new file mode 100644 index 0000000..3a5aa92 --- /dev/null +++ b/schemas/node.schema.json @@ -0,0 +1,675 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/node.schema.json", + "title": "Node", + "description": "One line of nodes.jsonl; spec/03-nodes.md.", + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "kind": { + "$ref": "common.schema.json#/$defs/nodeKind" + }, + "parent": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "type": "null" + } + ] + }, + "ord": { + "type": "integer", + "minimum": 0 + }, + "label": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "attrs": { + "type": "object", + "properties": { + "level": { + "type": "integer", + "minimum": 1 + }, + "columns": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "header_path": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + } + } + }, + "required": [ + "id", + "header_path" + ], + "additionalProperties": false + } + }, + "column": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "type": "null" + } + ] + }, + "rowspan": { + "type": "integer", + "minimum": 1 + }, + "colspan": { + "type": "integer", + "minimum": 1 + }, + "role": { + "enum": [ + "data", + "column-header", + "row-header", + "row-group-header" + ] + }, + "header_path": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + } + }, + "ordered": { + "type": "boolean" + }, + "marker": { + "type": "string", + "minLength": 1 + }, + "variant": { + "type": "string", + "minLength": 1 + }, + "image": { + "type": "object", + "properties": { + "sha256": { + "$ref": "common.schema.json#/$defs/hash" + }, + "media_type": { + "type": "string", + "minLength": 1 + }, + "native": { + "type": "boolean" + }, + "dpi": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "sha256", + "media_type", + "native" + ], + "additionalProperties": false + }, + "crop": { + "type": "object", + "properties": { + "sha256": { + "$ref": "common.schema.json#/$defs/hash" + }, + "media_type": { + "type": "string", + "minLength": 1 + }, + "dpi": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "sha256", + "media_type", + "dpi" + ], + "additionalProperties": false + }, + "figure_text": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "text": { + "type": "string", + "minLength": 1 + }, + "role": { + "enum": [ + "axis-label", + "tick-label", + "legend", + "annotation", + "other" + ] + }, + "page_fp": { + "$ref": "common.schema.json#/$defs/hash" + }, + "boxes": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/box" + }, + "minItems": 1 + } + }, + "required": [ + "id", + "text", + "role" + ], + "additionalProperties": false + } + } + }, + "required": [], + "additionalProperties": false, + "minProperties": 1 + }, + "content": {}, + "withheld": { + "const": true + }, + "fidelity": { + "$ref": "common.schema.json#/$defs/level" + }, + "prov": { + "type": "object", + "properties": { + "witnesses": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "minItems": 1, + "uniqueItems": true + }, + "backend": { + "type": "string", + "minLength": 1 + }, + "reading": { + "type": "string", + "minLength": 1 + }, + "corroborated_by": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "uniqueItems": true + } + }, + "required": [], + "additionalProperties": false + }, + "text_hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "match_hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "align_key": { + "$ref": "common.schema.json#/$defs/hash" + }, + "own_hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "node_hash": { + "$ref": "common.schema.json#/$defs/hash" + } + }, + "required": [ + "id", + "kind", + "parent", + "ord", + "text_hash", + "match_hash", + "align_key", + "own_hash", + "node_hash" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "kind": { + "enum": [ + "sentence", + "cell", + "reference", + "authors", + "keywords" + ] + } + } + }, + "then": { + "anyOf": [ + { + "required": [ + "withheld" + ] + }, + { + "required": [ + "content" + ], + "properties": { + "content": { + "$ref": "runs.schema.json" + } + } + } + ] + } + }, + { + "if": { + "properties": { + "kind": { + "enum": [ + "equation", + "equation-line" + ] + } + } + }, + "then": { + "anyOf": [ + { + "required": [ + "withheld" + ] + }, + { + "required": [ + "content" + ], + "properties": { + "content": { + "type": "object", + "properties": { + "notation": { + "enum": [ + "tex", + "typst" + ] + }, + "source": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "notation", + "source" + ], + "additionalProperties": false + } + } + } + ] + } + }, + { + "if": { + "properties": { + "kind": { + "enum": [ + "code", + "algorithm" + ] + } + } + }, + "then": { + "anyOf": [ + { + "required": [ + "withheld" + ] + }, + { + "required": [ + "content" + ], + "properties": { + "content": { + "type": "object", + "properties": { + "language": { + "type": "string", + "minLength": 1 + }, + "text": { + "type": "string" + } + }, + "required": [ + "text" + ], + "additionalProperties": false + } + } + } + ] + } + }, + { + "if": { + "properties": { + "kind": { + "not": { + "enum": [ + "sentence", + "cell", + "reference", + "authors", + "keywords", + "equation", + "equation-line", + "code", + "algorithm" + ] + } + } + } + }, + "then": { + "not": { + "anyOf": [ + { + "required": [ + "content" + ] + }, + { + "required": [ + "withheld" + ] + }, + { + "required": [ + "fidelity" + ] + } + ] + } + } + }, + { + "if": { + "properties": { + "kind": { + "not": { + "enum": [ + "section", + "figure", + "panel", + "table", + "theorem", + "footnote", + "equation", + "equation-line", + "reference", + "code", + "algorithm" + ] + } + } + } + }, + "then": { + "not": { + "required": [ + "label" + ] + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "section" + } + } + }, + "then": { + "required": [ + "attrs" + ], + "properties": { + "attrs": { + "required": [ + "level" + ] + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "not": { + "enum": [ + "section", + "table", + "cell", + "row", + "list", + "item", + "theorem", + "panel" + ] + } + } + } + }, + "then": { + "not": { + "required": [ + "attrs" + ] + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "section" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "level" + ] + } + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "table" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "columns" + ] + } + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "cell" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "column", + "rowspan", + "colspan", + "role" + ] + } + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "row" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "header_path" + ] + } + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "list" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "ordered" + ] + } + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "item" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "marker" + ] + } + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "theorem" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "variant" + ] + } + } + } + } + }, + { + "if": { + "properties": { + "kind": { + "const": "panel" + } + } + }, + "then": { + "properties": { + "attrs": { + "propertyNames": { + "enum": [ + "image", + "crop", + "figure_text" + ] + } + } + } + } + } + ] +} diff --git a/schemas/page.schema.json b/schemas/page.schema.json new file mode 100644 index 0000000..4dcc78d --- /dev/null +++ b/schemas/page.schema.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/page.schema.json", + "title": "Page", + "description": "One line of pages.jsonl; spec/07-geometry.md.", + "type": "object", + "properties": { + "witness": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "page": { + "type": "integer", + "minimum": 1 + }, + "page_fp": { + "$ref": "common.schema.json#/$defs/hash" + }, + "size": { + "$ref": "common.schema.json#/$defs/size" + }, + "page_label": { + "type": "string", + "minLength": 1 + }, + "text_layer": { + "type": "boolean" + }, + "stamps_removed": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/key" + }, + "minItems": 1 + } + }, + "required": [ + "witness", + "page", + "page_fp", + "size", + "text_layer" + ], + "additionalProperties": false +} diff --git a/schemas/policy.schema.json b/schemas/policy.schema.json new file mode 100644 index 0000000..2dfc968 --- /dev/null +++ b/schemas/policy.schema.json @@ -0,0 +1,143 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/policy.schema.json", + "title": "Team rights policy", + "description": "scienting-policy/1: a signed decision that resolves unknown uses; spec/14-rights.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-policy/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "project": { + "$ref": "common.schema.json#/$defs/key" + }, + "applies_to": { + "type": "object", + "properties": { + "basis": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/basis" + }, + "minItems": 1 + }, + "license": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/spdx" + }, + "minItems": 1 + }, + "doi_prefixes": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 1 + }, + "witnesses": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/hash" + }, + "minItems": 1 + } + }, + "required": [], + "additionalProperties": false, + "minProperties": 1 + }, + "uses": { + "type": "object", + "properties": { + "read": { + "$ref": "common.schema.json#/$defs/tri" + }, + "tdm": { + "$ref": "common.schema.json#/$defs/tri" + }, + "redistribute": { + "$ref": "common.schema.json#/$defs/tri" + }, + "quote-public": { + "$ref": "common.schema.json#/$defs/tri" + }, + "accessible-copy": { + "$ref": "common.schema.json#/$defs/tri" + }, + "ai": { + "type": "object", + "properties": { + "internal/local": { + "$ref": "common.schema.json#/$defs/tri" + }, + "internal/tenancy": { + "$ref": "common.schema.json#/$defs/tri" + }, + "internal/outside-no-retention": { + "$ref": "common.schema.json#/$defs/tri" + }, + "internal/outside": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/local": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/tenancy": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/outside-no-retention": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/outside": { + "$ref": "common.schema.json#/$defs/tri" + } + }, + "required": [], + "additionalProperties": false + } + }, + "required": [], + "additionalProperties": false + }, + "statement": { + "type": "string", + "minLength": 1 + }, + "by": { + "$ref": "common.schema.json#/$defs/key" + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + }, + "valid_until": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/time" + }, + { + "type": "null" + } + ] + }, + "signature": { + "$ref": "common.schema.json#/$defs/signature" + } + }, + "required": [ + "format", + "id", + "applies_to", + "uses", + "statement", + "by", + "at", + "valid_until", + "signature" + ], + "additionalProperties": false +} diff --git a/schemas/profile.schema.json b/schemas/profile.schema.json new file mode 100644 index 0000000..0b14b29 --- /dev/null +++ b/schemas/profile.schema.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/profile.schema.json", + "title": "Team profile", + "description": "scienting-profile/1: what backend conditions ask about a team; spec/14-rights.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-profile/1" + }, + "team": { + "$ref": "common.schema.json#/$defs/key" + }, + "purpose": { + "enum": [ + "research", + "personal", + "education", + "startup", + "commercial" + ] + }, + "revenue_or_funding_usd": { + "anyOf": [ + { + "type": "object", + "properties": { + "at_most": { + "anyOf": [ + { + "type": "integer", + "minimum": 0 + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "at_most" + ], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "competes_with": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "uniqueItems": true + }, + { + "type": "null" + } + ] + }, + "recorded_by": { + "$ref": "common.schema.json#/$defs/key" + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + } + }, + "required": [ + "format", + "team", + "purpose", + "revenue_or_funding_usd", + "competes_with", + "recorded_by", + "at" + ], + "additionalProperties": false +} diff --git a/schemas/project.schema.json b/schemas/project.schema.json new file mode 100644 index 0000000..ef8a284 --- /dev/null +++ b/schemas/project.schema.json @@ -0,0 +1,265 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/project.schema.json", + "title": "Project", + "description": "scienting-project/1: a team's curated set of documents and people; spec/20-projects.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-project/1" + }, + "key": { + "$ref": "common.schema.json#/$defs/key" + }, + "store": { + "$ref": "common.schema.json#/$defs/key" + }, + "name": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 1 + }, + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "person": { + "type": "string", + "minLength": 1 + }, + "role": { + "enum": [ + "owner", + "editor", + "reader", + "guest" + ] + }, + "keys": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/key" + }, + "uniqueItems": true + } + }, + "required": [ + "person", + "role", + "keys" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "documents": { + "type": "array", + "items": { + "type": "object", + "properties": { + "doc": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + }, + "reason": { + "type": "string", + "minLength": 1 + }, + "tags": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/key" + }, + "uniqueItems": true + }, + "status": { + "type": "object", + "additionalProperties": { + "enum": [ + "unread", + "reading", + "read" + ] + } + } + }, + "required": [ + "doc", + "reason" + ], + "additionalProperties": false + } + }, + "paths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "title": { + "type": "string", + "minLength": 1 + }, + "steps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "enum": [ + "document", + "node", + "claim", + "layer" + ] + }, + "ref": { + "type": "string", + "minLength": 1 + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "type", + "ref" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "id", + "title", + "steps" + ], + "additionalProperties": false + } + }, + "layers": { + "type": "array", + "items": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:layer:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + } + }, + "datasets": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/datasetId" + } + }, + "views": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/key" + } + }, + "drafts": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + } + }, + "claims": { + "type": "object", + "properties": { + "lode": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "lode" + ], + "additionalProperties": false + }, + "settings": { + "type": "object", + "properties": { + "digit_rule": { + "enum": [ + "all", + "anchored-sections", + "none" + ] + }, + "drift_threshold": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "spot_check": { + "type": "object", + "properties": { + "rate": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "minimum": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "rate", + "minimum" + ], + "additionalProperties": false + }, + "rights_unknown": { + "enum": [ + "refuse", + "warn" + ] + }, + "stages": { + "$ref": "common.schema.json#/$defs/key" + }, + "log": { + "type": "object", + "description": "The project's transparency log (spec/23): its origin, the roster keys that witness it, and how many must cosign a checkpoint.", + "properties": { + "origin": { + "type": "string", + "pattern": "^[^\\n]+$", + "minLength": 1 + }, + "witnesses": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/key" + }, + "uniqueItems": true + }, + "threshold": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "origin", + "witnesses", + "threshold" + ], + "additionalProperties": false + } + }, + "required": [], + "additionalProperties": false + } + }, + "required": [ + "format", + "key", + "name", + "members", + "documents" + ], + "additionalProperties": false +} diff --git a/schemas/proof.schema.json b/schemas/proof.schema.json new file mode 100644 index 0000000..60424d5 --- /dev/null +++ b/schemas/proof.schema.json @@ -0,0 +1,94 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/proof.schema.json", + "title": "Merkle proof", + "description": "scienting-proof/1: an RFC 9162 inclusion proof of one item of a receipt, or a consistency proof between two revisions of a document's history; spec/08-fidelity.md §8.5, spec/11-corrections.md §11.5.", + "type": "object", + "properties": { + "format": { + "const": "scienting-proof/1" + }, + "kind": { + "enum": [ + "inclusion", + "consistency" + ] + }, + "receipt": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "doc": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + }, + "item": { + "type": "array", + "minItems": 1 + }, + "index": { + "type": "integer", + "minimum": 0 + }, + "size": { + "type": "integer", + "minimum": 1 + }, + "root": { + "$ref": "common.schema.json#/$defs/hash" + }, + "from_rev": { + "type": "integer", + "minimum": 0 + }, + "to_rev": { + "type": "integer", + "minimum": 0 + }, + "from_root": { + "$ref": "common.schema.json#/$defs/hash" + }, + "to_root": { + "$ref": "common.schema.json#/$defs/hash" + }, + "path": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/hash" + } + } + }, + "required": [ + "format", + "kind", + "path" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "kind": { + "const": "inclusion" + } + } + }, + "then": { + "required": [ + "receipt", + "item", + "index", + "size", + "root" + ] + }, + "else": { + "required": [ + "doc", + "from_rev", + "to_rev", + "from_root", + "to_root" + ] + } + } + ] +} diff --git a/schemas/provenance.schema.json b/schemas/provenance.schema.json new file mode 100644 index 0000000..ed5ad2a --- /dev/null +++ b/schemas/provenance.schema.json @@ -0,0 +1,154 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/provenance.schema.json", + "title": "Provenance", + "description": "provenance.json of a package; spec/12-package.md.", + "type": "object", + "properties": { + "tools": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "version": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name", + "version" + ], + "additionalProperties": false + } + }, + "backends": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "version": { + "type": "string", + "minLength": 1 + }, + "declaration": { + "$ref": "common.schema.json#/$defs/hash" + } + }, + "required": [ + "name", + "version" + ], + "additionalProperties": false + } + }, + "readings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 1 + }, + "witness": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "backend": { + "type": "string", + "minLength": 1 + }, + "sha256": { + "$ref": "common.schema.json#/$defs/hash" + } + }, + "required": [ + "id", + "witness", + "backend", + "sha256" + ], + "additionalProperties": false + } + }, + "stages": { + "type": "array", + "items": { + "type": "object", + "properties": { + "stage": { + "enum": [ + "acquire", + "read", + "witness", + "assemble", + "reconcile", + "segment", + "locate", + "structure", + "figures", + "mint", + "suspects", + "review", + "gate", + "finalize", + "export", + "hand" + ] + }, + "tool": { + "type": "string", + "minLength": 1 + }, + "inputs": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/hash" + } + }, + "output": { + "$ref": "common.schema.json#/$defs/hash" + }, + "processor": { + "$ref": "common.schema.json#/$defs/processor" + }, + "uses": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + }, + "job": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "stage", + "processor" + ], + "additionalProperties": false + } + }, + "session": { + "type": "object" + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "tools" + ], + "additionalProperties": false +} diff --git a/schemas/qa-report.schema.json b/schemas/qa-report.schema.json new file mode 100644 index 0000000..a17988d --- /dev/null +++ b/schemas/qa-report.schema.json @@ -0,0 +1,91 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/qa-report.schema.json", + "title": "QA report", + "description": "scienting-qa-report/1: reviewer error bounds for a delivery; spec/08-fidelity.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-qa-report/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "delivery": { + "type": "string", + "minLength": 1 + }, + "docs": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + }, + "minItems": 1 + }, + "receipts": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "minItems": 1 + }, + "reviewers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "$ref": "common.schema.json#/$defs/key" + }, + "sampled": { + "type": "integer", + "minimum": 1 + }, + "errors": { + "type": "integer", + "minimum": 0 + }, + "confidence": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "method": { + "const": "clopper-pearson" + }, + "bound": { + "$ref": "common.schema.json#/$defs/decimal" + } + }, + "required": [ + "key", + "sampled", + "errors", + "confidence", + "method", + "bound" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "by": { + "$ref": "common.schema.json#/$defs/key" + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + }, + "signature": { + "$ref": "common.schema.json#/$defs/signature" + } + }, + "required": [ + "format", + "id", + "docs", + "receipts", + "reviewers", + "by", + "at", + "signature" + ], + "additionalProperties": false +} diff --git a/schemas/receipt.schema.json b/schemas/receipt.schema.json new file mode 100644 index 0000000..5ea36a9 --- /dev/null +++ b/schemas/receipt.schema.json @@ -0,0 +1,219 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/receipt.schema.json", + "title": "Review receipt", + "description": "scienting-receipt/1; spec/08-fidelity.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-receipt/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "doc": { + "$ref": "common.schema.json#/$defs/documentKey" + }, + "rev": { + "type": "integer", + "minimum": 0 + }, + "level": { + "$ref": "common.schema.json#/$defs/receiptLevel" + }, + "scope": { + "type": "string", + "pattern": "^(all|section:[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6}|page:[1-9][0-9]*|targeted:[a-z0-9-]+|qa:[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25})$" + }, + "nodes": { + "type": "array", + "items": { + "type": "array", + "prefixItems": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "$ref": "common.schema.json#/$defs/hash" + } + ], + "minItems": 2, + "maxItems": 2 + } + }, + "records": { + "type": "array", + "items": { + "type": "array", + "prefixItems": [ + { + "enum": [ + "annotation", + "digitization", + "correction", + "layer", + "checklist" + ] + }, + { + "$ref": "common.schema.json#/$defs/recordId" + }, + { + "$ref": "common.schema.json#/$defs/hash" + } + ], + "minItems": 3, + "maxItems": 3 + } + }, + "root": { + "$ref": "common.schema.json#/$defs/hash" + }, + "evidence": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/evidence" + } + }, + "by": { + "$ref": "common.schema.json#/$defs/key" + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + }, + "qa": { + "type": "object", + "properties": { + "of": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "key": { + "$ref": "common.schema.json#/$defs/key" + }, + "seed": { + "$ref": "common.schema.json#/$defs/base64" + }, + "rate": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "minimum": { + "type": "integer", + "minimum": 1 + }, + "sample": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "minItems": 1 + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "node": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "kind": { + "enum": [ + "word", + "number", + "equation", + "structure", + "other" + ] + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "node" + ], + "additionalProperties": false + } + } + }, + "required": [ + "of", + "key", + "seed", + "rate", + "minimum", + "sample", + "errors" + ], + "additionalProperties": false + }, + "export_of": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "keyed": { + "$ref": "common.schema.json#/$defs/hashing" + }, + "signature": { + "$ref": "common.schema.json#/$defs/signature" + } + }, + "required": [ + "format", + "id", + "doc", + "rev", + "level", + "scope", + "nodes", + "root", + "evidence", + "by", + "at", + "signature" + ], + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "scope": { + "pattern": "^qa:" + } + } + }, + "then": { + "required": [ + "qa" + ] + }, + "else": { + "not": { + "required": [ + "qa" + ] + } + } + }, + { + "anyOf": [ + { + "properties": { + "nodes": { + "minItems": 1 + } + } + }, + { + "required": [ + "records" + ], + "properties": { + "records": { + "minItems": 1 + } + } + } + ] + } + ] +} diff --git a/schemas/reference.schema.json b/schemas/reference.schema.json new file mode 100644 index 0000000..7c0812c --- /dev/null +++ b/schemas/reference.schema.json @@ -0,0 +1,73 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/reference.schema.json", + "title": "Reference record", + "description": "One line of references.jsonl; spec/10-references.md.", + "type": "object", + "properties": { + "node": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "label": { + "type": "string", + "minLength": 1 + }, + "csl": { + "type": "object" + }, + "resolution": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "const": "doi" + }, + "doi": { + "type": "string", + "pattern": "^10\\.[0-9]{4,9}/[^ ]+$" + } + }, + "required": [ + "type", + "doi" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "document" + }, + "doc": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + } + }, + "required": [ + "type", + "doc" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "none" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + } + }, + "required": [ + "node", + "resolution" + ], + "additionalProperties": false +} diff --git a/schemas/revocation.schema.json b/schemas/revocation.schema.json new file mode 100644 index 0000000..a42634e --- /dev/null +++ b/schemas/revocation.schema.json @@ -0,0 +1,91 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/revocation.schema.json", + "title": "Revocation", + "description": "scienting-revocation/1; spec/08-fidelity.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-revocation/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "receipt": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "signer": { + "$ref": "common.schema.json#/$defs/key" + }, + "period": { + "type": "object", + "properties": { + "from": { + "$ref": "common.schema.json#/$defs/time" + }, + "to": { + "$ref": "common.schema.json#/$defs/time" + } + }, + "required": [ + "from", + "to" + ], + "additionalProperties": false + }, + "reason": { + "type": "string", + "minLength": 1 + }, + "by": { + "$ref": "common.schema.json#/$defs/key" + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + }, + "signature": { + "$ref": "common.schema.json#/$defs/signature" + } + }, + "required": [ + "format", + "id", + "reason", + "by", + "at", + "signature" + ], + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "receipt" + ], + "not": { + "anyOf": [ + { + "required": [ + "signer" + ] + }, + { + "required": [ + "period" + ] + } + ] + } + }, + { + "required": [ + "signer", + "period" + ], + "not": { + "required": [ + "receipt" + ] + } + } + ] +} diff --git a/schemas/rights.schema.json b/schemas/rights.schema.json new file mode 100644 index 0000000..eef5a21 --- /dev/null +++ b/schemas/rights.schema.json @@ -0,0 +1,150 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/rights.schema.json", + "title": "Rights record", + "description": "scienting-rights/1: a witness's license, basis and uses; spec/14-rights.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-rights/1" + }, + "license": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/license" + }, + { + "type": "null" + } + ] + }, + "basis": { + "$ref": "common.schema.json#/$defs/basis" + }, + "uses": { + "type": "object", + "properties": { + "read": { + "$ref": "common.schema.json#/$defs/tri" + }, + "tdm": { + "$ref": "common.schema.json#/$defs/tri" + }, + "redistribute": { + "$ref": "common.schema.json#/$defs/tri" + }, + "quote-public": { + "$ref": "common.schema.json#/$defs/tri" + }, + "accessible-copy": { + "$ref": "common.schema.json#/$defs/tri" + }, + "ai": { + "type": "object", + "properties": { + "internal/local": { + "$ref": "common.schema.json#/$defs/tri" + }, + "internal/tenancy": { + "$ref": "common.schema.json#/$defs/tri" + }, + "internal/outside-no-retention": { + "$ref": "common.schema.json#/$defs/tri" + }, + "internal/outside": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/local": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/tenancy": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/outside-no-retention": { + "$ref": "common.schema.json#/$defs/tri" + }, + "external/outside": { + "$ref": "common.schema.json#/$defs/tri" + } + }, + "required": [], + "additionalProperties": false + } + }, + "required": [], + "additionalProperties": false + }, + "asserted_by": { + "type": "object", + "properties": { + "by": { + "type": "string", + "minLength": 1 + }, + "evidence": { + "type": "array", + "items": { + "type": "object", + "properties": { + "kind": { + "enum": [ + "license-url", + "contract", + "crossref-license", + "delivery", + "statement" + ] + }, + "url": { + "$ref": "common.schema.json#/$defs/url" + }, + "sha256": { + "$ref": "common.schema.json#/$defs/hash" + }, + "doi": { + "type": "string", + "minLength": 1 + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind" + ], + "additionalProperties": false + } + } + }, + "required": [ + "by", + "evidence" + ], + "additionalProperties": false + }, + "at": { + "$ref": "common.schema.json#/$defs/time" + }, + "valid_until": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/time" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "format", + "license", + "basis", + "uses", + "asserted_by", + "at", + "valid_until" + ], + "additionalProperties": false +} diff --git a/schemas/roster.schema.json b/schemas/roster.schema.json new file mode 100644 index 0000000..5d7feb1 --- /dev/null +++ b/schemas/roster.schema.json @@ -0,0 +1,118 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/roster.schema.json", + "title": "Roster", + "description": "scienting-roster/1: the keys that may sign; spec/08-fidelity.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-roster/1" + }, + "store": { + "$ref": "common.schema.json#/$defs/key" + }, + "keys": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "person": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "orcid": { + "type": "string", + "pattern": "^[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{3}[0-9X]$" + }, + "email": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "role": { + "description": "The holder's role in the team that keeps the roster; a key with the role owner may revoke any receipt (spec/08 §8.7).", + "enum": [ + "owner", + "editor", + "reader", + "guest" + ] + }, + "scheme": { + "enum": [ + "ed25519", + "ssh", + "gpg", + "sigstore", + "cose", + "ml-dsa-65" + ] + }, + "public": { + "type": "string", + "minLength": 1 + }, + "did": { + "type": "string", + "pattern": "^did:key:z[1-9A-HJ-NP-Za-km-z]+$", + "description": "The key as a did:key decentralized identifier, which the public key determines (spec/08 §8.7)." + }, + "purposes": { + "type": "array", + "items": { + "enum": [ + "sign", + "spot-check", + "export", + "witness" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "registered_at": { + "$ref": "common.schema.json#/$defs/time" + }, + "revoked_at": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/time" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "person", + "role", + "scheme", + "public", + "purposes", + "registered_at", + "revoked_at" + ], + "additionalProperties": false + } + } + }, + "required": [ + "format", + "store", + "keys" + ], + "additionalProperties": false +} diff --git a/schemas/runs.schema.json b/schemas/runs.schema.json new file mode 100644 index 0000000..836cf96 --- /dev/null +++ b/schemas/runs.schema.json @@ -0,0 +1,189 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/runs.schema.json", + "title": "Inline runs", + "description": "The runs of a sentence, cell, reference, authors or keywords node; spec/03-nodes.md.", + "type": "array", + "minItems": 1, + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "const": "text" + }, + "text": { + "type": "string", + "minLength": 1 + }, + "style": { + "type": "array", + "items": { + "enum": [ + "em", + "strong", + "sup", + "sub", + "sc", + "mono" + ] + }, + "minItems": 1, + "uniqueItems": true + } + }, + "required": [ + "kind", + "text" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "math" + }, + "notation": { + "enum": [ + "tex", + "typst" + ] + }, + "source": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "notation", + "source" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "cite" + }, + "refs": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "uniqueItems": true + }, + "text": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "refs", + "text" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "xref" + }, + "target": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "$ref": "common.schema.json#/$defs/address" + }, + { + "type": "null" + } + ] + }, + "text": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "target", + "text" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "fnmark" + }, + "footnote": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "type": "null" + } + ] + }, + "text": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "footnote", + "text" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "link" + }, + "url": { + "$ref": "common.schema.json#/$defs/url" + }, + "text": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "kind", + "url", + "text" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kind": { + "const": "equation" + }, + "node": { + "$ref": "common.schema.json#/$defs/nodeId" + } + }, + "required": [ + "kind", + "node" + ], + "additionalProperties": false + } + ] + } +} diff --git a/schemas/snapshot.schema.json b/schemas/snapshot.schema.json new file mode 100644 index 0000000..f19c269 --- /dev/null +++ b/schemas/snapshot.schema.json @@ -0,0 +1,120 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/snapshot.schema.json", + "title": "Draft snapshot", + "description": "scienting-snapshot/1: the pinned claims, quotations and datasets a draft cites; spec/21-drafts.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-snapshot/1" + }, + "store": { + "$ref": "common.schema.json#/$defs/key" + }, + "made_at": { + "$ref": "common.schema.json#/$defs/time" + }, + "quotes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "address": { + "$ref": "common.schema.json#/$defs/address" + }, + "anchor": { + "$ref": "anchor.schema.json" + }, + "text": { + "type": "string", + "minLength": 1 + }, + "fidelity": { + "$ref": "common.schema.json#/$defs/level" + }, + "result": { + "enum": [ + "current", + "changed-below", + "moved", + "reattached" + ] + } + }, + "required": [ + "address", + "anchor", + "text", + "fidelity", + "result" + ], + "additionalProperties": false + } + }, + "claims": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ref": { + "type": "string", + "minLength": 1 + }, + "pin": { + "type": "string", + "minLength": 1 + }, + "level": { + "type": "string", + "minLength": 1 + }, + "standing": { + "type": "string", + "minLength": 1 + }, + "rendering": { + "type": "string", + "minLength": 1 + }, + "typst": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "ref", + "pin" + ], + "additionalProperties": false + } + }, + "datasets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/datasetId" + }, + "hash": { + "$ref": "common.schema.json#/$defs/hash" + } + }, + "required": [ + "id", + "hash" + ], + "additionalProperties": false + } + } + }, + "required": [ + "format", + "store", + "made_at", + "quotes", + "claims", + "datasets" + ], + "additionalProperties": false +} diff --git a/schemas/spot-check.schema.json b/schemas/spot-check.schema.json new file mode 100644 index 0000000..128d9ed --- /dev/null +++ b/schemas/spot-check.schema.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/spot-check.schema.json", + "title": "Spot-check seed payload", + "description": "scienting-spot-check/1: the payload a spot-check key signs to seed a sample; it names a receipt by its record hash and is never a file of its own; spec/08-fidelity.md §8.8.", + "type": "object", + "properties": { + "format": { + "const": "scienting-spot-check/1" + }, + "receipt": { + "$ref": "common.schema.json#/$defs/hash" + } + }, + "required": [ + "format", + "receipt" + ], + "additionalProperties": false +} diff --git a/schemas/stages.schema.json b/schemas/stages.schema.json new file mode 100644 index 0000000..5272eb1 --- /dev/null +++ b/schemas/stages.schema.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/stages.schema.json", + "title": "Stage requirements", + "description": "scienting-stages/1: the uses each stage needs; configuration, not code; spec/14-rights.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-stages/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "note": { + "type": "string", + "minLength": 1 + }, + "stages": { + "type": "object", + "minProperties": 1, + "propertyNames": { + "$ref": "common.schema.json#/$defs/key" + }, + "additionalProperties": { + "type": "object", + "properties": { + "uses": { + "type": "array", + "items": { + "enum": [ + "read", + "tdm", + "redistribute", + "quote-public", + "accessible-copy" + ] + }, + "uniqueItems": true + }, + "ai": { + "type": "object", + "properties": { + "purpose": { + "enum": [ + "internal", + "external" + ] + }, + "processors": { + "type": "array", + "items": { + "$ref": "common.schema.json#/$defs/processor" + }, + "minItems": 1, + "uniqueItems": true + } + }, + "required": [ + "purpose" + ], + "additionalProperties": false + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "uses" + ], + "additionalProperties": false + } + } + }, + "required": [ + "format", + "id", + "stages" + ], + "additionalProperties": false +} diff --git a/schemas/stamps.schema.json b/schemas/stamps.schema.json new file mode 100644 index 0000000..3f02e84 --- /dev/null +++ b/schemas/stamps.schema.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/stamps.schema.json", + "title": "Stamp rules", + "description": "scienting-stamps/1: download-stamp line rules for page fingerprints; spec/07-geometry.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-stamps/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "learned": { + "type": "boolean" + }, + "note": { + "type": "string", + "minLength": 1 + }, + "rules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "pattern": { + "type": "string", + "minLength": 1 + }, + "where": { + "enum": [ + "any", + "margin" + ] + }, + "margin": { + "type": "number", + "exclusiveMinimum": 0 + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "id", + "pattern", + "where" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "format", + "id", + "rules" + ], + "additionalProperties": false +} diff --git a/schemas/submission.schema.json b/schemas/submission.schema.json new file mode 100644 index 0000000..aabe3b3 --- /dev/null +++ b/schemas/submission.schema.json @@ -0,0 +1,109 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/submission.schema.json", + "title": "Submission", + "description": "scienting-submission/1: a student's answer, under a pseudonym; spec/19-exercises.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-submission/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "exercise": { + "type": "string", + "pattern": "^tag:scient\\.ing,2026:annotation:[a-z0-9][a-z0-9._-]*/[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$" + }, + "doc": { + "$ref": "common.schema.json#/$defs/qualifiedKey" + }, + "rev": { + "type": "integer", + "minimum": 0 + }, + "student": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9-]{3,63}$" + }, + "answers": { + "type": "object", + "properties": { + "anchors": { + "type": "array", + "items": { + "$ref": "anchor.schema.json" + } + }, + "verdict": { + "enum": [ + "supports", + "partly", + "does-not", + "cannot-tell" + ] + }, + "chain": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "anchor.schema.json" + } + } + }, + "value": { + "$ref": "common.schema.json#/$defs/decimal" + }, + "flags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "anchor": { + "$ref": "anchor.schema.json" + }, + "verdict": { + "enum": [ + "supports", + "partly", + "does-not", + "cannot-tell" + ] + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "anchor", + "verdict" + ], + "additionalProperties": false + } + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [], + "additionalProperties": false + }, + "submitted_at": { + "$ref": "common.schema.json#/$defs/time" + } + }, + "required": [ + "format", + "id", + "exercise", + "doc", + "rev", + "student", + "answers", + "submitted_at" + ], + "additionalProperties": false +} diff --git a/schemas/suspect.schema.json b/schemas/suspect.schema.json new file mode 100644 index 0000000..8612b76 --- /dev/null +++ b/schemas/suspect.schema.json @@ -0,0 +1,77 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/suspect.schema.json", + "title": "Suspect", + "description": "scienting-suspect/1: a doubtful reading for review; spec/05-hashes.md.", + "type": "object", + "properties": { + "format": { + "const": "scienting-suspect/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "kind": { + "enum": [ + "word", + "number", + "equation", + "structure", + "join", + "added", + "dropped", + "boundary", + "reading" + ] + }, + "node": { + "anyOf": [ + { + "$ref": "common.schema.json#/$defs/nodeId" + }, + { + "type": "null" + } + ] + }, + "reading": { + "type": "string", + "minLength": 1 + }, + "a": { + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ] + }, + "b": { + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ] + }, + "crop": { + "$ref": "common.schema.json#/$defs/hash" + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "format", + "id", + "kind" + ], + "additionalProperties": false +} diff --git a/schemas/value-anchor.schema.json b/schemas/value-anchor.schema.json new file mode 100644 index 0000000..74feed4 --- /dev/null +++ b/schemas/value-anchor.schema.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/value-anchor.schema.json", + "title": "Value anchor", + "description": "One line of a dataset's anchors.jsonl: where one value came from; spec/15-datasets.md.", + "type": "object", + "properties": { + "resource": { + "$ref": "common.schema.json#/$defs/key" + }, + "row": { + "$ref": "common.schema.json#/$defs/key" + }, + "field": { + "type": "string", + "minLength": 1 + }, + "anchor": { + "$ref": "anchor.schema.json" + }, + "digitization": { + "$ref": "common.schema.json#/$defs/recordId" + }, + "series": { + "type": "string", + "minLength": 1 + }, + "point": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "resource", + "row", + "field" + ], + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "anchor" + ] + }, + { + "required": [ + "digitization", + "series", + "point" + ] + } + ] +} diff --git a/schemas/view.schema.json b/schemas/view.schema.json new file mode 100644 index 0000000..4d7269f --- /dev/null +++ b/schemas/view.schema.json @@ -0,0 +1,115 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/view.schema.json", + "title": "View", + "description": "A Vega-Lite specification whose usermeta.scienting pins its data: scienting-view/1; spec/17-views.md.", + "type": "object", + "required": [ + "$schema", + "usermeta" + ], + "properties": { + "$schema": { + "type": "string", + "pattern": "^https://vega\\.github\\.io/schema/vega-lite/v[0-9]+(\\.[0-9]+)*\\.json$" + }, + "usermeta": { + "type": "object", + "required": [ + "scienting" + ], + "properties": { + "scienting": { + "type": "object", + "properties": { + "format": { + "const": "scienting-view/1" + }, + "id": { + "$ref": "common.schema.json#/$defs/key" + }, + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "$ref": "common.schema.json#/$defs/datasetId" + }, + "dataset": { + "$ref": "common.schema.json#/$defs/datasetId" + }, + "hash": { + "$ref": "common.schema.json#/$defs/hash" + }, + "resource": { + "$ref": "common.schema.json#/$defs/key" + } + }, + "required": [ + "name", + "dataset", + "hash", + "resource" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "computation": { + "type": "object", + "properties": { + "claim": { + "type": "string", + "minLength": 1 + }, + "pin": { + "type": "string", + "minLength": 1 + }, + "runtime": { + "const": "pyodide" + }, + "inputs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "param": { + "type": "string", + "minLength": 1 + }, + "name": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "param", + "name" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "claim", + "pin", + "runtime", + "inputs" + ], + "additionalProperties": false + } + }, + "required": [ + "format", + "id", + "data" + ], + "additionalProperties": false + } + } + } + } +} diff --git a/schemas/witnesses.schema.json b/schemas/witnesses.schema.json new file mode 100644 index 0000000..695687d --- /dev/null +++ b/schemas/witnesses.schema.json @@ -0,0 +1,108 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperspec.scient.ing/schemas/witnesses.schema.json", + "title": "Witnesses", + "description": "witnesses.json of a package; spec/02-model.md.", + "type": "object", + "properties": { + "witnesses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "common.schema.json#/$defs/nodeId" + }, + "sha256": { + "$ref": "common.schema.json#/$defs/hash" + }, + "size": { + "type": "integer", + "minimum": 0 + }, + "kind": { + "enum": [ + "pdf", + "jats", + "latex", + "html", + "epub", + "typst", + "xml", + "image", + "other" + ] + }, + "media_type": { + "type": "string", + "minLength": 1 + }, + "pages": { + "type": "integer", + "minimum": 1 + }, + "text_layer": { + "type": "boolean" + }, + "version_label": { + "type": "string", + "minLength": 1 + }, + "origin": { + "type": "object", + "properties": { + "source": { + "enum": [ + "publisher", + "repository", + "preprint-server", + "author", + "team", + "licensed-delivery", + "library", + "other" + ] + }, + "url": { + "$ref": "common.schema.json#/$defs/url" + }, + "doi": { + "type": "string", + "minLength": 1 + }, + "retrieved_at": { + "$ref": "common.schema.json#/$defs/time" + }, + "note": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "source" + ], + "additionalProperties": false + }, + "rights": { + "$ref": "rights.schema.json" + } + }, + "required": [ + "id", + "sha256", + "size", + "kind", + "media_type", + "origin", + "rights" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "witnesses" + ], + "additionalProperties": false +} diff --git a/spec/00-introduction.md b/spec/00-introduction.md new file mode 100644 index 0000000..2e49901 --- /dev/null +++ b/spec/00-introduction.md @@ -0,0 +1,89 @@ +# 0. Introduction + +This chapter is for three readers. +A newcomer, who knows what a scientific paper and a citation are, finds what the specification covers and how to read it. +An implementer, who will write a reader, writer, converter or checker, finds the rules for conformance, identifiers, versions and status. +An expert, who knows the neighboring standards, finds the status of each format and how the specification relates to those standards. + +## 0.1 Scope + +Tools that read, correct, annotate and check papers can work together only if they agree on the files they exchange. +The specification defines that data: documents and their packages, anchors, receipts, rights records, layers, exercises, datasets, digitizations, views, projects and bundles. +A package is a document stored as a set of files; an anchor is a reference to a place in a document that stays checkable when the document changes. + +It defines data, not programs. +A conforming file can be read, checked and loaded without any particular program, and every rule is stated so that a second implementation, in any language, computes the same bytes. + +The specification does not replace the standards around it. +JATS ([ANSI/NISO Z39.96-2024](https://www.niso.org/publications/z3996-2024-jats)) remains the format for publishers and archives to exchange journal articles; here it is only one kind of input to a document. +Layers are [W3C Web Annotations](https://www.w3.org/TR/annotation-model/) with a custom selector for the anchor. [docs/comparison.md](../docs/comparison.md) compares the specification with the standards near it and says where each is the better choice. + +The [guides](../docs/README.md) explain what each format is for, and the [rationale](../docs/rationale.md) why its rules are what they are. + +## 0.2 Conformance language + +The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED, MAY and OPTIONAL are to be interpreted as described in RFC 2119 and RFC 8174 when, and only when, they appear in capitals. + +The suite is the set of test vectors (inputs paired with the outputs every implementation must compute) and fixtures (example files, valid and invalid) in the repository. [22](22-conformance.md) describes it. + +The specification distinguishes three classes of implementation. + +| Class | Does | Must | +| --- | --- | --- | +| Producer | Writes files in a format. | Write only files that validate, with values computed as specified. | +| Consumer | Reads files in a format. | Accept every valid file, and refuse every file the suite lists as invalid, naming the rule. | +| Validator | Decides whether a file is valid. | Check every rule in [22](22-conformance.md) that the file's contents allow it to check. | + +An implementation states, for each format, which versions it reads and writes. + +## 0.3 Format identifiers and versions + +Every format has an identifier of the form `scienting-/`, such as `scienting-doc/1`. +The identifier tells a reader which rules apply to a file. +The prefix `scienting-` is the namespace of the formats. +The namespace is not the name of this repository, paperspec, and formats are named after what they hold. + +A file or record that can travel on its own carries its identifier in a `format` property. +The anchor in `fixtures/records/anchor-leaf.json` begins `{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1", ...`. +Records inside a package file whose format the manifest fixes, such as the lines of `nodes.jsonl`, do not repeat it. + +A change that makes a valid file invalid, or that changes a computed value, is a breaking change and needs a new major version, with a migration. +Adding an optional property, a node kind, a run kind, or an enumeration value is a minor change. +A consumer of version *n* MUST refuse a major version it does not know, and SHOULD warn on, but accept, enumeration values added in a later minor version. + +The specification as a whole is versioned with semantic versioning; this is version 0.1.0. [registry/formats.json](../registry/formats.json) lists every format with its media type, schema and status. + +## 0.4 Status + +Each format has one of three statuses, listed in [registry/formats.json](../registry/formats.json). +In version 0.1.0 the registry lists 32 formats: 19 are `candidate` and 13 are `provisional`; none is `reserved`. + +| Status | Meaning | +| --- | --- | +| `candidate` | Complete, with vectors and fixtures, and ready to implement. | +| `provisional` | Complete, but expected to change as implementations gain experience with it. | +| `reserved` | Named and shaped, but not yet specified in full. | + +Some fields matter only to some users: a personal library has no use for spot-checks, and a team that reads only open-access papers rarely needs a policy. +Those fields are defined anyway, so that files move between a personal library and a team's store without conversion. +A consumer that does not use a field MUST still preserve it when it rewrites a file. + +## 0.5 How the repository is arranged + +A normative folder defines what conforming means. +The other folders help people use the specification. + +| Path | Holds | Normative | +| --- | --- | --- | +| `spec/` | These chapters. | Yes | +| `schemas/` | JSON Schemas, draft 2020-12. | Yes | +| `sql/` | Table definitions for SQLite, Dolt and PostgreSQL, and the SQLite bundle. | Yes | +| `context/` | The JSON-LD context for layers. | Yes | +| `registry/` | Formats, rule IDs, stamp rules and the default stage requirements. | Yes | +| `vectors/` | Test vectors, one case per line. | Yes | +| `fixtures/` | Valid packages and records, invalid packages, and the keys that signed them. | Yes | +| `tools/` | The programs that compute and check the vectors and fixtures, and load packages into SQLite. | No | +| `docs/` | Guides for people getting to know the formats. | No | + +The programs in `tools/` compute every expected value, so that none is typed by hand. +They are not a library, and implementations conform to the chapters and the vectors. diff --git a/spec/01-conventions.md b/spec/01-conventions.md new file mode 100644 index 0000000..feb6c33 --- /dev/null +++ b/spec/01-conventions.md @@ -0,0 +1,95 @@ +# 1. Shared conventions + +These rules apply to every format. + +## 1.1 Canonical JSON + +Canonical JSON is the JSON Canonicalization Scheme of RFC 8785. +In brief: no whitespace between tokens; object members sorted by their names compared as sequences of UTF-16 code units; strings escaped only where JSON requires, with `\b`, `\t`, `\n`, `\f`, `\r`, `\"` and `\\` for those characters and `\u00xx` with lowercase hex for the other characters below U+0020; numbers written as ECMAScript writes a double. +Strings are not normalized: canonical JSON keeps every code point as given. +A document containing a lone surrogate, `NaN` or an infinity has no canonical form and is invalid. + +Every hash of a JSON value in these specifications is a hash of its canonical JSON, encoded as UTF-8. +The vectors in `canonical-json.jsonl` give JSON text to parse as IEEE 754 doubles and the canonical output. + +A store may keep its own canonical form for its stored hashes; that form is outside this text. + +## 1.2 Numbers + +A decimal that carries meaning is a string, so that `310.0` and `1.5260` keep their printed digits. +The schemas call this a `decimal`: an optional minus sign, an integer part without leading zeros, and an optional fraction. +JSON numbers are used only for counts, indexes, offsets, sizes and geometry. + +Geometry is in PDF points. +A producer SHOULD round coordinates to hundredths of a point, which keeps their canonical form short and identical across languages. + +## 1.3 Hashes + +A hash is SHA-256, written as 64 lowercase hexadecimal digits. +Six digits are for display and for pins in addresses; no record stores a shortened hash. +`document.json` names the function in `hashing.algorithm`, `sha-256` in this version, and every hash in the package, its records and its proofs uses the one function the document names; a consumer refuses an algorithm it does not implement (`doc.hash.algorithm`). +Property names such as `sha256` and `page_fp` belong to that function, so a later algorithm arrives as a new major version of the formats whose values it changes, with the name in the data letting two versions share a store. +Inside a team's own store, hashes are plain SHA-256; any content value that leaves the team is keyed, as [5.8](05-hashes.md#58-keyed-hashes) defines. + +## 1.4 Text normalization for hashing + +To normalize a string for hashing: + +1. Apply Unicode Normalization Form C. +2. Replace every maximal run of whitespace characters with one U+0020. +3. Remove a leading and a trailing U+0020. + +Whitespace means the 25 characters with the Unicode property `White_Space`: U+0009 to U+000D, U+0020, U+0085, U+00A0, U+1680, U+2000 to U+200A, U+2028, U+2029, U+202F, U+205F and U+3000. +U+200B ZERO WIDTH SPACE is not whitespace. + +Stored text is kept exactly as witnessed; normalization applies only when a value is computed. +The vectors in `normalize.jsonl` cover the cases, including the angstrom sign, which NFC turns into Å. + +Normalization forms, General Categories and the `White_Space` property are those of Unicode 16.0. +A later Unicode version can change a decomposition or a category, and with it a hash, so an implementation states the Unicode version its character data comes from, the reference tools refuse to run on another, and moving the formats to a later version is a change to every format that hashes text ([0.3](00-introduction.md#03-format-identifiers-and-versions)). + +## 1.5 Character offsets + +Offsets count Unicode code points, never UTF-16 code units or bytes. +An offset pair `[start, end]` names the code points from `start` up to but not including `end`. +A browser implementation converts to UTF-16 at its edge; `offsets.jsonl` gives both forms for text with characters outside the Basic Multilingual Plane. + +## 1.6 Times + +A time is UTC, written `YYYY-MM-DDTHH:MM:SSZ`, with no fractions. +A date is `YYYY`, `YYYY-MM` or `YYYY-MM-DD`. + +## 1.7 Determinism + +Every value these specifications define is a pure function of its inputs. +Readings from machine-learning backends are not deterministic, so a producer caches them by the hash of their inputs and records them in the package's provenance, and never recomputes them silently. +From the cached readings onward, the same inputs and tool versions MUST give byte-identical files. +No file carries the time it was written, unless the time is part of the record, as a receipt's is. + +## 1.8 IDs and keys + +| Kind | Form | Pattern | +| --- | --- | --- | +| Node ID | Seven characters of lowercase Crockford base32, the first a letter. | `^[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6}$` | +| Record ID | 7 to 26 such characters, the first a letter. Derived records use 13. | `^[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$` | +| Work key | A Scholar-style part, a hyphen and 4 to 51 characters of Crockford base32 ([2.4](02-model.md#24-work-and-document-keys)). At most 128 characters. | `^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}$` | +| Document key | A work key, with a dotted suffix for a version other than the version of record. At most 128 characters. | `^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(\.[a-z0-9][a-z0-9-]*)*$` | +| Key | A store, project or source key, or a legacy document key kept as an alias. At most 128 characters. | `^[a-z0-9][a-z0-9._-]*$` | +| Alias | A legacy ID; it always holds a `.`, `_` or `-`, so it never looks like a node ID. | `^[a-z0-9][a-z0-9._-]*[._-][a-z0-9._-]*$` | +| Dataset ID | `ds-` and a key. | `^ds-[a-z0-9][a-z0-9._-]*$` | + +The Crockford alphabet is `0123456789abcdefghjkmnpqrstvwxyz`; it has no `i`, `l`, `o` or `u`. +Its 22 letters are `abcdefghjkmnpqrstvwxyz`. +Because the first character is a letter, every ID is a valid HTML `id`, CSS selector and URL fragment without escaping. +A key qualified by its store, `smithlab/cornell1995second`, names a document anywhere. + +## 1.9 Files + +JSON Lines files hold one record per line, in canonical JSON, each line ending with one U+000A. +JSON files hold one value in canonical JSON followed by one U+000A. +So a corrected sentence is a one-line change, and every file has exactly one valid byte sequence. +Each JSON Lines file has a defined order, given where the file is defined. + +## 1.10 Prose + +Prose in these formats, and in this repository, is US English, one sentence per line. diff --git a/spec/02-model.md b/spec/02-model.md new file mode 100644 index 0000000..2b6ed3b --- /dev/null +++ b/spec/02-model.md @@ -0,0 +1,95 @@ +# 2. Works, versions, witnesses and documents + +## 2.1 Four objects + +| Object | Is | Identified by | +| --- | --- | --- | +| Work | The intellectual work, across all its versions. | A work key ([2.4](#24-work-and-document-keys)), and `same_as` identifiers: `doi:`, `arxiv:`, `isbn:`, `pmid:`, `pmcid:`, `openalex:`, `url:` or `lode:`. | +| Version | One expression of the work: a preprint, an accepted manuscript, the version of record, an erratum, Supporting Information, a draft. | The work's key and a version type, with an optional sequence number and date. | +| Witness | One file of a version: a PDF, JATS XML, a LaTeX source archive, an HTML page, an EPUB, a Typst project. | The SHA-256 of its bytes. | +| Document | The text established for one version from one or more witnesses. | A key, and a root hash per revision. | + +A document's key is its work's key, with a suffix for anything other than the version of record: `cornell1995second-saqk`, `cornell1995second-saqk.si`, `dong2026machine-1ard.v2`. +Supporting Information is its own document, with its own pages, numbering and references, related to its article by `supplement-of`. +A textbook is a work whose chapters are documents related by `part-of`. +A draft is a document of kind `draft`. + +Keys are immutable once a document is shared. +A renamed document keeps its old keys in `aliases`. + +## 2.2 `document.json` + +| Property | Required | Holds | +| --- | --- | --- | +| `format` | Yes | `scienting-doc/1`. | +| `key` | Yes | The document key. | +| `store` | No | The store that holds it, when the package says so. | +| `aliases` | No | Earlier keys. | +| `kind` | Yes | `article`, `supplement`, `chapter`, `book`, `thesis`, `report`, `draft`, `course-material` or `other`. | +| `work` | Yes | `{key, same_as}`. | +| `version` | Yes | `{type, seq?, date?}`, where `type` is `preprint`, `submitted`, `accepted`, `version-of-record`, `erratum`, `retraction`, `supplement`, `draft` or `other`. | +| `relations` | Yes | A list of `{type, target}`; `type` is `supplement-of`, `part-of`, `version-of`, `erratum-of`, `retraction-of` or `translation-of`, and `target` a key, optionally store-qualified. | +| `meta` | Yes | The version's bibliographic record, as one CSL-JSON item. | +| `language` | Yes | A BCP 47 tag. | +| `license` | No | The document's license as stated: `{spdx?, text?, url?}`. Rights are per witness ([14](14-rights.md)). | +| `policy` | Yes | The text policy: `full`, or `checks-only` ([12.5](12-package.md#125-text-policies)). | +| `hashing` | Yes | How content values are computed: `{scheme: "plain"}`, a team HMAC or a page-derived key ([5.8](05-hashes.md#58-keyed-hashes)). | +| `root` | Yes | The root node's `node_hash`. | +| `meta_hash` | Yes | The metadata hash ([5.9](05-hashes.md#59-the-metadata-hash)). | +| `history` | Yes | The history root: the root of the tree over the package's corrections ([11.5](11-corrections.md#115-the-history-root)). | +| `rev` | Yes | The revision: the index of the last correction applied, or 0. | +| `counts` | Yes | `{nodes, leaves}`. | +| `fidelity` | Yes | `{lowest, counts}`: the lowest level among leaves, or null when there are none, and the number of leaves at each level, computed as [8.2](08-fidelity.md#82-levels) defines. | + +The schema is `document.schema.json`. + +## 2.3 `witnesses.json` + +`witnesses.json` is an object with one property, `witnesses`, a non-empty list in which each witness is: + +| Property | Required | Holds | +| --- | --- | --- | +| `id` | Yes | The witness ID: seven letter-first base32 characters encoding the SHA-256, as [4.6](04-identity.md#46-record-ids) defines. | +| `sha256` | Yes | The SHA-256 of the file. | +| `size` | Yes | Its size in bytes. | +| `kind` | Yes | `pdf`, `jats`, `latex`, `html`, `epub`, `typst`, `xml`, `image` or `other`. | +| `media_type` | Yes | Its media type. | +| `pages` | No | The number of pages, for a witness that has pages. | +| `text_layer` | No | Whether a PDF has a text layer; a scan has none. | +| `version_label` | No | The version as the witness labels it. | +| `origin` | Yes | `{source, url?, doi?, retrieved_at?, note?}`, where `source` is `publisher`, `repository`, `preprint-server`, `author`, `team`, `licensed-delivery`, `library` or `other`. | +| `rights` | Yes | The rights record, `scienting-rights/1` ([14](14-rights.md)). | + +The witness's bytes are not part of the package; they live in the team's asset store, by SHA-256. +The SHA-256 is the exact identity of one file. +Because publishers stamp each download, two copies of one paper rarely share it; page fingerprints identify their pages instead ([7](07-geometry.md)). + +## 2.4 Work and document keys + +A work key names a work the way a reader would, and never collides: a Scholar-style citation key, a hyphen, and the first characters of a hash of the work's identity. + +```text +vaswani2017attention-a241 +└─── Scholar part ──┘ └hash┘ +``` + +**The Scholar part** is built as Google Scholar builds its BibTeX keys, from the CSL-JSON `meta` of the version: + +1. the first author's family name: `family`, or the part of a `literal` name before a comma, else its last word that is not a suffix such as Jr. or III; folded to ASCII with NFKD, lower-cased, letters only, so `Müller` gives `muller` and `O'Brien` gives `obrien`; no author, or a name with no Latin letters, gives `anon`; +2. the year of `issued`, when it has four digits, else nothing; +3. the first word of `title` that is not a stop word, folded the same way, letters and digits only, with apostrophes removed and other punctuation splitting words; no such word gives nothing. + +The stop words are `a an the of on in for to and or at by with from as into onto about toward towards via is are be its it this that these those`. + +**The identity** is the work's first identifier among `doi`, `arxiv`, `isbn`, `pmid`, `pmcid` and `openalex` in `same_as`, in that order, written `:` with a DOI's ASCII letters lower-cased. +A work with none has the identity `meta:|<year>|<family>` from the same folded parts. +`url:` and `lode:` identifiers name copies and claims, not the work, and never enter the identity. + +**The hash part** is the leading bits of SHA-256 of `scienting-key/1:` followed by the identity, in UTF-8, written in lowercase Crockford base32, five bits a character: four characters, or, when another work in the store already holds that key, six, eight and so on until the key is free. +A key is minted once, when the work enters a store, and never recomputed: a corrected title or a year revised later leaves it alone, while the hash of an identifier still shows which work the key names. +A work key matches `^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}$`. + +**The document key** is the work key for the version of record, and the work key with a suffix for any other version: `.si` for Supporting Information, `.v<seq>` for a preprint, submitted, accepted or draft version with a sequence number, else a dot and the version type: `cornell1995second-saqk`, `cornell1995second-saqk.si`, `dong2026machine-1ard.v2`. +A validator checks that the document key is the work key with the version's suffix (`doc.key.work`), and that a key whose identity is an identifier carries that identifier's hash (`doc.key.suffix`); a metadata identity may have been corrected since the key was minted, so it is not held to the key. +Store, project and source keys keep the form `^[a-z0-9][a-z0-9._-]*$`, as do legacy document keys kept in `aliases`. +`keys.jsonl` pins the Scholar parts, identities, hashes and document keys, with accented names, name suffixes, missing years and authors, and the lengthening that settles a collision. diff --git a/spec/03-nodes.md b/spec/03-nodes.md new file mode 100644 index 0000000..ab1b071 --- /dev/null +++ b/spec/03-nodes.md @@ -0,0 +1,127 @@ +# 3. Nodes + +A document is a tree of nodes. +`nodes.jsonl` holds one node per line, in document order: the root first, then each node before its children, and siblings in order. + +## 3.1 The node record + +| Property | Required | Holds | +| --- | --- | --- | +| `id` | Yes | The node ID ([4](04-identity.md)). | +| `kind` | Yes | One of the kinds in [3.2](#32-kinds-and-children). | +| `parent` | Yes | The parent's ID, or null for the root. | +| `ord` | Yes | The position among its siblings, from 0. | +| `label` | No | The printed label (`2.3`, `Figure 2`, `(1)`, `a`), for kinds that take one. | +| `attrs` | No | Structural attributes, by kind ([3.4](#34-attributes)). | +| `content` | No | The node's own content, by kind ([3.3](#33-content)). | +| `withheld` | No | `true` when the policy withholds the content ([12.5](12-package.md#125-text-policies)). | +| `fidelity` | No | For leaves, the level the pipeline established: `F0`, `F1` or `F2` ([8.1](08-fidelity.md#81-levels-of-fidelity)). | +| `prov` | No | `{witnesses, backend?, reading?, corroborated_by?}`: the witness IDs the text came from, the backend, and the witnesses that agree. | +| `text_hash`, `match_hash`, `align_key`, `own_hash`, `node_hash` | Yes | The five content values ([5](05-hashes.md)). | + +Optional properties are omitted, never written as null. +The schema is `node.schema.json`. + +## 3.2 Kinds and children + +| Kind | May contain | Content | Label | +| --- | --- | --- | --- | +| `document` | `front`, `section`, `back` | | | +| `front` | `title`, `authors`, `abstract`, `keywords`, `notes` | | | +| `title` | `sentence` | | | +| `authors` | | runs | | +| `abstract` | blocks, `section` | | | +| `keywords` | | runs | | +| `notes` | `footnote`, `paragraph` | | | +| `section` | `heading` first, then blocks and `section` | | Yes | +| `heading` | `sentence` | | | +| `paragraph` | `sentence` | | | +| `sentence` | `equation` | runs | | +| `equation` | `equation-line` | math | Yes | +| `equation-line` | | math | Yes | +| `figure` | `panel`, `caption`, `figure-note` | | Yes | +| `panel` | | | Yes | +| `caption` | `sentence` | | | +| `figure-note` | `sentence` | | | +| `table` | `caption`, `table-head`, `table-body`, `table-note` | | Yes | +| `table-head`, `table-body` | `row` | | | +| `table-note` | `sentence` | | | +| `row` | `cell` | | | +| `cell` | | runs | | +| `list` | `item` | | | +| `item`, `quote` | blocks | | | +| `code`, `algorithm` | | verbatim | Yes | +| `theorem` | blocks | | Yes | +| `footnote` | `sentence` | | Yes | +| `back` | `acknowledgments`, `references`, `appendix`, `notes` | | | +| `acknowledgments` | blocks | | | +| `references` | `reference` | | | +| `reference` | | runs | Yes | +| `appendix` | `section` | | | + +Blocks are `paragraph`, `equation`, `figure`, `table`, `list`, `quote`, `code`, `algorithm`, `theorem` and `footnote`. + +These rules also hold: + +1. Exactly one node is a root, and it is a `document`. +2. A `heading` is a section's first child, and a section has at most one. +3. `front`, `back`, `title`, `authors`, `abstract`, `keywords`, `caption`, `table-head`, `table-body`, `acknowledgments` and `references` occur at most once among their siblings. +4. A `table` has exactly one `table-body`. +5. `title`, `heading`, `paragraph`, `caption`, `figure-note`, `table-note`, `table-head`, `table-body`, `row`, `list`, `item`, `quote`, `theorem`, `footnote` and `appendix` have at least one child. +6. Only the kinds marked in the table take a `label`. +7. A body without headings, as in a letter, is a section with no heading. + +Kinds outside this list are refused; a new kind is a minor version. +Page breaks, running heads and columns are not nodes: they are geometry ([7](07-geometry.md)). + +## 3.3 Content + +| Content | Kinds | Shape | +| --- | --- | --- | +| Runs | `sentence`, `cell`, `reference`, `authors`, `keywords` | A non-empty list of inline runs ([3.5](#35-inline-runs)). | +| Math | `equation`, `equation-line` | `{notation, source}`: `tex` or `typst`, and the source as written. | +| Verbatim | `code`, `algorithm` | `{language?, text}`. | + +Other kinds have no `content`. +Derived renderings, such as MathML, are not content; they live in `derived/` ([12.7](12-package.md#127-derived-files)). + +## 3.4 Attributes + +| Kind | Attribute | Holds | +| --- | --- | --- | +| `section` | `level` (required) | 1 for a section, 2 for a subsection, and so on. | +| `table` | `columns` | The column definitions: `[{id, header_path}]`, where `header_path` lists header cell IDs, outermost first ([9.2](09-figures-tables-equations.md#92-tables)). | +| `cell` | `column`, `rowspan`, `colspan`, `role` | The column's ID, spans (default 1), and `data` (default), `column-header`, `row-header` or `row-group-header`. | +| `row` | `header_path` | The cell IDs that label the row, outermost first. | +| `list` | `ordered` | Whether the list is numbered. | +| `item` | `marker` | The printed marker. | +| `theorem` | `variant` | The printed kind: Theorem, Lemma, Definition, Proof, Remark. | +| `panel` | `image`, `crop`, `figure_text` | The image asset, a crop, and the text found inside the panel ([9.1](09-figures-tables-equations.md#91-figures-and-panels)). | + +No other kind carries `attrs`, and each kind carries only its own attributes. + +## 3.5 Inline runs + +| Run | Properties | Plain projection | +| --- | --- | --- | +| `text` | `text`, and optional `style`: a sorted list of distinct values from `em`, `strong`, `sup`, `sub`, `sc`, `mono`, never both `sup` and `sub`. | The text. | +| `math` | `notation` (`tex` or `typst`), `source`. | `$` + source + `$` | +| `cite` | `refs`: reference node IDs; `text`: the printed form, such as `23`, `[1,2]` or `(Smith, 2019)`. | The printed form. | +| `xref` | `target`: a node ID in this document, an address in another, or null when not yet resolved; `text`. | The printed form. | +| `fnmark` | `footnote`: a footnote's ID, or null; `text`: the mark. | The mark. | +| `link` | `url`, `text`. | The text. | +| `equation` | `node`: the ID of an equation child of the sentence. | `$$` + that equation's source + `$$` | + +Runs are canonical: no `text` run is empty, and no two adjacent `text` runs have the same style list. +A sentence's `equation` runs name its `equation` children, each once, in the children's order, and a sentence has no other children. +A display equation the sentence runs through is thus part of the sentence, while keeping its own ID and hashes. + +## 3.6 The plain projection + +The plain projection of a node with runs is the concatenation of its runs' projections. +That of an equation or an equation line is `$$` + source + `$$`, and that of a verbatim node is its text. +That of any other node is the plain projections of its text leaves joined with one U+0020. + +A node's text leaves are found by walking its subtree in document order and stopping at `sentence`, `cell`, `reference`, `authors`, `keywords`, `code` and `algorithm` nodes, and at `equation` nodes whose parent is not a sentence; an `equation-line` is never a text leaf. + +Offsets, quotations and the text hash are all defined on the plain projection as stored, before normalization. diff --git a/spec/04-identity.md b/spec/04-identity.md new file mode 100644 index 0000000..7c93f36 --- /dev/null +++ b/spec/04-identity.md @@ -0,0 +1,73 @@ +# 4. Identity + +A node's ID is a name, not a position. +It carries no meaning, and once a document is established it is never recomputed, reassigned or reused. + +## 4.1 Letter-first base32 + +To encode a SHA-256 digest *d* (32 bytes) as a letter-first ID of *n* characters: + +1. The first character is the letter at index `d[0] mod 22` of `abcdefghjkmnpqrstvwxyz`. +2. Read the bytes `d[1]` to `d[31]` as one big-endian bit string. +3. Each further character is the Crockford character for the next five bits, from the most significant end. + +Node IDs have seven characters, about 34.5 bits; derived record IDs have 13. +`ids.jsonl` in the vectors gives digests and their encodings. + +## 4.2 Minting node IDs + +A node's ID is minted from SHA-256 of the canonical JSON of the array `["scienting-id/1", doc_key, kind, text_hash, occurrence]`, encoded with seven characters. +`text_hash` is the plain, never keyed, text hash of the node ([5.1](05-hashes.md#51-the-five-values)). + +When a document is established, nodes are minted in document order. +A node's occurrence starts at the number of earlier nodes with the same kind and text hash; while the resulting ID is already taken, the occurrence increases by one. +So a fresh conversion of the same input mints the same IDs. + +A node added later, by an `insert` or a `split`, starts at occurrence 0 and increases while the ID is taken by any live, retired or alias ID of the document. + +Columns and figure-text items are not nodes, but they take IDs from the same rule and the same document-wide set, after the nodes: +a column with kind `column` and the text hash of its header cells' plain projections joined with U+0020; +a figure-text item with kind `figure-text` and the text hash of its text. + +## 4.3 Permanence, retirement and aliases + +| Rule | Detail | +| --- | --- | +| Permanence | Once established, an ID never changes, and no other node ever takes it. | +| Retirement | A `merge` or a `delete` retires IDs ([11](11-corrections.md)). A merge records the surviving node as the successor; a delete records none. | +| Aliases | Legacy IDs, such as the `b-p03-text-004` block IDs an earlier extract format used, are recorded as aliases of the node that now holds that text. | +| Labels | What people say, such as "Eq. 3" or "Table S1", is a `label`, never an ID. | +| Display paths | Tools may show a path such as `§2.3 ¶4 s2`; it is never stored or cited. | + +## 4.4 `ids.jsonl` + +Each line is one entry. + +| Property | Holds | +| --- | --- | +| `id` | The retired node ID, or the alias. | +| `kind` | `retired` or `alias`. | +| `successor` | For a retirement, the successor's ID, or null for a deletion; for an alias, the live node it names. | +| `node_kind` | For a retirement, the kind the node had. | +| `rev` | For a retirement, the index of the correction that retired it. | + +Aliases come first, sorted by ID; retirements follow, sorted by `rev` and then ID. +No ID is both live and in the table, every successor is live or itself in the table, and every alias names a live node. + +## 4.5 Store-qualified names + +A document key qualified by its store, `smithlab/cornell1995second`, names a document anywhere, and an address with a store names a node anywhere ([6.1](06-anchors.md#61-addresses)). + +## 4.6 Record IDs + +A record that is never edited takes its ID from its own content, as 13 letter-first characters of a hash: + +| Record | Hash | +| --- | --- | +| Receipt, revocation, policy | The record hash: SHA-256 of the record without `id` and `signature` ([8.4](08-fidelity.md#84-record-hashes-and-signatures)). | +| Correction | SHA-256 of the record without `id`. | +| Annotation | SHA-256 of the annotation without `id`, `status`, `receipt` and `modified`, as created. | +| Submission, digitization | SHA-256 of the record without `id`. | + +A witness ID is the seven-character letter-first encoding of the witness's SHA-256 itself. +Other records, such as layers and qa reports, MAY use any record ID unique in their store. diff --git a/spec/05-hashes.md b/spec/05-hashes.md new file mode 100644 index 0000000..e1f6772 --- /dev/null +++ b/spec/05-hashes.md @@ -0,0 +1,196 @@ +# 5. Content values + +Each node carries five content values, each for one job. +No value covers the node's own ID, its geometry, its provenance or its fidelity. +So re-witnessing a page or proofreading a sentence changes none of them, while changing one character changes the `text_hash` and `node_hash` of that sentence. + +In this chapter *H* is SHA-256 written as hexadecimal; under a keyed scheme, *H* is HMAC-SHA-256 under the key ([5.8](#58-keyed-hashes)). + +## 5.1 The five values + +| Value | Definition | Used for | +| --- | --- | --- | +| `text_hash` | *H*(normalize(plain projection)) | Quotations and verbatim checks, where every character counts. | +| `match_hash` | *H*(strict projection) | Certifying that two witnesses agree, and recognizing the same text elsewhere. | +| `align_key` | *H*(lossy projection) | Proposing alignments. It never certifies anything. | +| `own_hash` | *H*(canonical JSON of the node's own content, [5.2](#52-own-content)) | Anchors on containers that have content of their own. | +| `node_hash` | *H*(canonical JSON of `{"own": own_hash, "children": [each child's node_hash, in order]}`) | Pins on leaves; the root hash; knowing that something below has changed. | + +Normalization is that of [1.4](01-conventions.md#14-text-normalization-for-hashing). +Because each `node_hash` covers its children's, the root's `node_hash` covers the whole tree (it is a hash over canonical JSON of `{own, children}`, not an RFC 6962 Merkle root, which [8.5](08-fidelity.md#85-merkle-roots) defines for receipts): a correction to one sentence changes that sentence's values and the `node_hash` of each ancestor, and nothing else. +`hashes.jsonl` gives every value for every node of a small document, with each node's own content. + +## 5.2 Own content + +A node's own content is an object with its `kind` and these members, and nothing else: + +| Kinds | Members | +| --- | --- | +| Kinds that take a label | `label`: the label, or null. | +| `sentence`, `cell`, `reference`, `authors`, `keywords` | `runs`: the runs as stored, except that each `equation` run is reduced to `{"kind": "equation"}`, since an ID is never content. | +| `equation`, `equation-line` | `notation`, `source`. | +| `code`, `algorithm` | `language` (or null), `text`. | +| `section` | `level`, and `heading`: the `text_hash` of its heading, or null. | +| `table` | `columns`, as stored. | +| `cell` | `column`, `rowspan`, `colspan` and `role`, with defaults 1, 1 and `data` when absent. | +| `theorem` | `variant`, or null. | + +So paragraphs, rows, lists, items and the other containers without content have the same `own_hash` as every node of their kind, and are never judged by it. +Own content covers stored values exactly; it is not normalized. +A table's columns name header cells by ID, so fixing a header cell changes that cell, not the table. + +## 5.3 The strict projection + +The strict projection folds notation to one canonical linear form and keeps structure, so that it can certify agreement. +It is computed over a node's runs, or its math, as follows; for other nodes it is the strict projections of the text leaves joined with U+0020, then step 3. + +1. Apply NFC to every string, then project each run: + + | Run | Strict projection | + | --- | --- | + | `text` with `sup` | `^{` + inner + `}`, or only primes when the content is only primes ([5.4](#54-simple-notation)) | + | `text` with `sub` | `_{` + inner + `}` | + | other `text`, `link` | The text, with Unicode script characters folded and dashes before digits folded ([5.4](#54-simple-notation)) | + | `math`, `equation` | The canonical linear form when the source is simple; U+FFFC when it is complex | + | `cite`, `xref`, `fnmark` | U+FFF9 + the printed form with whitespace removed + U+FFFB | + + Concatenate the results. +2. Apply NFKC, which folds ligatures, the micro sign and Greek variant letters. +3. Collapse whitespace to one U+0020 and trim, as [1.4](01-conventions.md#14-text-normalization-for-hashing) does. + +Folding scripts before NFKC matters: NFKC alone would turn a superscript ² into a plain 2 and erase the structure the projection exists to keep. +Marking citations matters for the same reason: "10" followed by citation 3 must not agree with the text "103". + +Each complex run also yields a complex key, `notation:source`, with the source in NFC and every whitespace character removed. +A node's complex keys are listed in order. +Two readings agree only when their `match_hash` values are equal and their complex keys are equal, run by run; this is stage 1 of canonical math. +A later minor version may add stage 2, which replaces U+FFFC with canonical MathML; that would change `match_hash` and `align_key` values but no `text_hash`, `own_hash` or `node_hash`, so no anchor would go stale. + +## 5.4 Simple notation + +A character is simple, after folding, when it is: + +1. a letter: General Category L in the Latin blocks U+0041–U+024F and U+1E00–U+1EFF, or in the Greek blocks U+0370–U+03FF, without the Coptic letters U+03E2–U+03EF, and U+1F00–U+1FFF; or U+00B5 MICRO SIGN; +2. a digit: General Category Nd; or +3. one of `+ − = × ⋅ / < > ≤ ≥ ± ( ) ′ . ,`. + +Inside notation, characters fold: U+002D and U+2013 to U+2212 MINUS SIGN; U+00B7, U+2219 and U+22C5 to U+22C5 DOT OPERATOR; U+0027 and U+2032 to U+2032 PRIME. + +**The canonical linear form.** +Notation is a sequence of atoms; an atom has a base (possibly empty), a count of primes, an optional subscript and an optional superscript, each itself a sequence of atoms. +An atom is written as its base, then its primes as U+2032, then `_{`, the subscript and `}`, then `^{`, the superscript and `}`. +A superscript that holds only bare primes becomes primes on its atom. +There are no spaces in the form, and a script with no base attaches to the character before it, so all of `$H_2O$`, `H$_2$O`, `$\mathrm{H}_{2}\mathrm{O}$`, `H<sub>2</sub>O` and `H₂O` project to `H_{2}O`. + +**TeX sources** are read as tokens: control words (`\` and ASCII letters, with following whitespace skipped), control symbols (`\` and one other character), and single characters, with whitespace and `~` ignored. + +| Token | Meaning | +| --- | --- | +| `{` … `}` | A group; its atoms are spliced in. A script on a group of more than one atom makes the source complex; a script after an empty group applies to the atom before it, or to an empty base, so `{}^{14}C` is `^{14}C`. | +| `_`, `^` | A subscript or superscript of the previous atom (or of an empty base), taking one argument: a group, a command or a character. A second script of the same kind is complex. | +| `'` | A prime on the previous atom. | +| `\mathrm`, `\text`, `\textrm`, `\mathup` | A wrapper: its argument's atoms are spliced in. | +| `\rm` | Ignored. | +| `\,` `\;` `\:` `\!`, a backslash before a space, `\quad` `\qquad` `\enspace` `\thinspace` `\medspace` `\thickspace` | Spacing, ignored. | +| `\alpha` … `\omega`, `\varepsilon`, `\vartheta`, `\varkappa`, `\varpi`, `\varrho`, `\varsigma`, `\varphi`, `\Gamma` … `\Omega` | The Greek letter TeX typesets; `\epsilon` is ϵ and `\phi` is ϕ. | +| `\times` `\cdot` `\pm` `\le` `\leq` `\ge` `\geq` `\lt` `\gt` `\prime` `\AA` | × ⋅ ± ≤ ≤ ≥ ≥ < > ′ Å | +| `\left(`, `\right)` | Parentheses; any other delimiter is complex. | +| A simple character | An atom. | +| Anything else | The source is complex. | + +**Typst sources** are read as tokens: strings in double quotes (complex if they contain a backslash), identifiers (runs of letters, with `.` joining modifiers such as `plus.minus`), numbers (digits with an optional fraction), the two-character operators `<=` and `>=`, and single characters, with whitespace ignored. + +| Token | Meaning | +| --- | --- | +| `_`, `^` | A script of the previous atom; its argument is a parenthesized group, whose parentheses are dropped, or one token. | +| `(` … `)` elsewhere | Literal parentheses around a group. | +| `'` | A prime. | +| A string | Its characters, with whitespace removed. | +| A one-letter identifier, a number | Its characters. | +| `upright(…)` | A wrapper. | +| `alpha` … `omega`, `Alpha` … `Omega`, and `epsilon.alt`, `theta.alt`, `phi.alt`, `pi.alt`, `rho.alt`, `sigma.alt`, `kappa.alt`, `beta.alt` | The Greek letter Typst renders; `epsilon` is ε and `phi` is φ. | +| `plus` `minus` `times` `dot` `dot.op` `dot.c` `plus.minus` `lt` `gt` `lt.eq` `gt.eq` `eq` `prime` `slash`, and `<=` `>=` | + − × ⋅ ⋅ ⋅ ± < > ≤ ≥ = ′ / ≤ ≥ | +| `thin` `med` `thick` `quad` `wide` `space` | Spacing, ignored. | +| `/`, `*`, `#`, `&`, brackets, braces, any other identifier, and the operators `->`, `=>`, `!=`, `<-`, `==`, `:=` | Complex. In Typst `/` is a fraction. | + +NFKC later folds the variant letters (ϵ to ε, ϕ to φ, ϑ to θ), so TeX's and Typst's defaults agree in the projection. + +**Styled scripts.** +The inner form of a `sup` or `sub` text run is its text with whitespace removed and characters folded, when every character is simple or a Unicode script character; otherwise it is the text with whitespace collapsed and trimmed. + +**Unicode script characters** are those whose decomposition mapping is tagged `<super>` or `<sub>`, such as ², ⁻ and ₂. +In text, each maximal run of script characters of one kind folds to `^{` or `_{`, the folded bases, and `}`, when every base is simple; otherwise the run is left for NFKC to flatten. + +**Dashes in text.** +Outside notation, U+002D and U+2013 immediately before a digit become U+2212, so "10-20" and "10–20" agree; "CT–CT" keeps its dash. + +`notation.jsonl` covers every rule, and `projections.jsonl` with `projection-groups.jsonl` covers H₂O, cm⁻¹, 10⁻³ and K_r in every spelling, ligatures, the micro sign, citation marks and "103" against 10³. + +## 5.5 The lossy projection + +The lossy projection starts from the strict projection and: + +1. removes each `_{` and `^{` and the `}` that closes it, leaving the script's content in place, while other braces stay; +2. removes each mark, from U+FFF9 to the next U+FFFB; +3. applies Unicode full case folding, then NFKC; +4. deletes every whitespace character, every character of General Category Pd, and U+00AD SOFT HYPHEN. + +So "103" and 10³ share an `align_key` while their `match_hash` values differ, and "bond- length", "bond-length" and "bond length" share one too. +A node's prose length is the number of code points in its lossy projection other than U+FFFC. + +## 5.6 Alignment + +Two readings of a document are aligned as whole sentence sequences, never paragraph by paragraph, because backends disagree about paragraphs at page and column breaks. +Each reading is a list of sentences in document order, each with its strict projection, lossy projection, complex keys, container and context (the kind of its container: paragraph, heading, caption and so on). + +1. **Anchors.** A sentence is a candidate when its lossy projection occurs exactly once in each reading and its prose length is at least 20. + Take the candidates in the order of the first reading, and choose the longest subsequence whose positions in the second reading increase; among equally long ones, the one whose sequence of positions in the first reading is lexicographically smallest. +2. **Between anchors**, and before the first and after the last, align by the longest common subsequence of lossy projections. + Ties are broken deterministically: walking both segments from their start, pair two sentences whose lossy projections are equal; otherwise skip the first reading's sentence when the remainder without it has a common subsequence at least as long as without the second's, and skip the second's otherwise. +3. **Compare** each pair. + They agree when their strict projections and complex keys are equal. + Otherwise the pair is a suspect: of kind `number` when their numeric skeletons differ, else `equation` when their complex keys differ, else `word`. + The numeric skeleton keeps only digits, U+2212, `.`, `,`, `+`, `_{`, `^{` and `}`. +4. **Structure.** A pair whose contexts differ is also a `structure` suspect; two consecutive pairs that share a container in one reading but not in the other are a `join` suspect. +5. **Unplaced** sentences are `dropped` (in the first reading only) or `added` (in the second only). + +Paired sentences keep the first reading's ID even when they disagree, so a reading that lost a superscript is caught rather than accepted. +`alignment.jsonl` aligns two readings that exercise every rule, including two prose-thin sentences aligned by their order. + +## 5.7 Suspects + +A suspect, `scienting-suspect/1`, records a doubtful reading for review: its `id`, its `kind` (`word`, `number`, `equation`, `structure`, `join`, `added`, `dropped`, `boundary` for an uncertain sentence boundary, or `reading` for anything else), the node, the readings compared, an optional crop by SHA-256 and a note. +Suspects may travel in a package's `suspects.jsonl`, sorted by ID, until they are resolved. + +## 5.8 Keyed hashes + +A hash of a short text is not a secret: a withheld cell reading "310.0" is recovered by hashing guesses. +So every content value that leaves a team's store is keyed. + +| Where the value goes | `hashing` | Key | +| --- | --- | --- | +| The team's own store and bundles | `{"scheme": "plain"}` | None. | +| An export to another machine of the team, whatever its text policy | `{"scheme": "hmac-team", "key_id": …}` | The team key. | +| A public layer, or an export outside the team on a work whose text is withheld | `{"scheme": "hkdf-pages", "context": …, "pages": […]}` | A key derived from the witness's page fingerprints. | + +The destination chooses the scheme, not the text policy. +A checks-only package ([12.5](12-package.md#125-text-policies)) sent between the team's own machines is keyed with the team key, as `hale2026harmonic-damb.checks-only` is; sent to anyone outside the team, it is keyed with the page key. + +A keyed scheme replaces SHA-256 with HMAC-SHA-256 under its key in every content value, including the Merkle construction of `node_hash`, and in `meta_hash`. + +**The team key** is HKDF-SHA-256 (RFC 5869) with the team secret, at least 32 random bytes, as input keying material, the salt `scienting-team-key/1`, the info `scienting-hash/1` and length 32. +Its `key_id` is the first 16 hexadecimal digits of SHA-256 of the bytes `scienting-key-id/1` followed by the key. + +**The page key** is HKDF-SHA-256 with the concatenated 32-byte page fingerprints of the witness, in page order, as input keying material, the salt `scienting-page-key/1`, the UTF-8 of the context as info, and length 32. +The context names the export, such as `layer:smithlab/kp4m2x7q`, so two exports never share a key. +The export lists each page as its page hash, SHA-256 of `scienting-page-hash/1` followed by the fingerprint's 32 bytes, never the fingerprint itself. +A reader who holds the paper computes the fingerprints from their own copy, checks them against the page hashes and derives the key; someone who does not hold it sees only hashes of hashes. + +In keyed anchors, quotations become MACs over the normalized quotation and context texts become MACs over their normalized text ([6.3](06-anchors.md#63-keyed-anchors)). +Open-access documents under a license that allows redistribution need none of this. +`keyed.jsonl` gives the derivations and a case a non-holder cannot verify. + +## 5.9 The metadata hash + +`meta_hash` is *H* of the canonical JSON of `{work, version, relations, meta, language, license}` from `document.json`, with `license` null when absent. +Fixing an affiliation changes `meta_hash` and not the root. diff --git a/spec/06-anchors.md b/spec/06-anchors.md new file mode 100644 index 0000000..f63ae37 --- /dev/null +++ b/spec/06-anchors.md @@ -0,0 +1,123 @@ +# 6. Addresses and anchors + +## 6.1 Addresses + +An address names a node, optionally pinned to a hash and narrowed to a span: + +```abnf +address = [store "/"] key "#" node ["@" pin] ["[" start ":" end "]"] +store = lowalnum *(lowalnum / "." / "_" / "-") +key = workkey *("." lowalnum *(lowalnum / "-")) ; a document key (2.4) +workkey = LOWER *lowalnum "-" 4*51BASE32 +node = lowalnum *(lowalnum / "." / "_" / "-") ; a node ID or an alias +pin = 6HEXLOWER ; the first six digits of a node_hash +start = "0" / (%x31-39 *DIGIT) +end = "0" / (%x31-39 *DIGIT) +lowalnum = LOWER / DIGIT +LOWER = %x61-7A +BASE32 = DIGIT / %x61-68 / %x6A-6B / %x6D-6E / %x70-74 / %x76-7A ; Crockford, lowercase +``` + +`start` is not greater than `end`, and both are code-point offsets into the plain projection of the node in the pinned state. + +| Example | Names | +| --- | --- | +| `cornell1995second-saqk#k3m9q2a` | A sentence, whatever its current text. | +| `cornell1995second-saqk#k3m9q2a@4f1a0c` | That sentence as it read when its `node_hash` began `4f1a0c`. | +| `cornell1995second-saqk#k3m9q2a@4f1a0c[12:57]` | Code points 12 to 57 of its plain projection in that state. | +| `smithlab/cornell1995second#k3m9q2a` | The same sentence in the `smithlab` store. | + +On the web the node ID is the fragment: `…/smithlab/cornell1995second#k3m9q2a` lands on the sentence. +`addresses.jsonl` gives valid and invalid addresses and how each parses. + +## 6.2 The anchor + +An anchor, `scienting-anchor/1`, is the stored form of a pinned address, with enough context to survive change. +It is what extracts, annotations, dataset values and draft citations use. + +| Property | Required | Holds | +| --- | --- | --- | +| `format` | Yes | `scienting-anchor/1`. | +| `store` | No | The store. | +| `doc` | Yes | The document key. | +| `node` | Yes | The node ID, or a legacy alias. | +| `kind` | No, RECOMMENDED | The node's kind when the anchor was made. | +| `own_hash`, `node_hash` | Yes | The node's values when the anchor was made. | +| `span` | No | `[start, end]` in code points; present for span anchors. | +| `quote` | With a span, or on a leaf | `{exact, prefix?, suffix?}`, or `{exact_hash, length, prefix?, suffix?}` for quotations longer than 200 code points. | +| `context` | On a cell | `{table_label, row_path, column_path}`: the table's label and the normalized plain projections of the row's and column's header cells, outermost first. | +| `leaves` | On a container without content | `[[id, match_hash], …]`: every leaf below the node, in document order. | +| `rev` | Yes | The document's revision when the anchor was made. | +| `keyed` | No | The hashing scheme, when the anchor leaves the team ([6.3](#63-keyed-anchors)). | + +`exact` is the substring of the stored plain projection at the span, or the whole projection for a leaf anchor. +`prefix` and `suffix` are up to 32 code points before and after it, omitted when empty. +`exact_hash` is SHA-256 of the normalized quotation, and `length` its length in code points. + +Revisions are counted, not timed, because anchors are made on different machines and clocks disagree. + +## 6.3 Keyed anchors + +When an anchor leaves the team, in a public layer or on a work whose text is withheld, it carries `keyed`, and: + +1. `own_hash` and `node_hash` are computed under the key; +2. `quote` becomes `{mac, length, prefix_mac?, suffix_mac?}`, each MAC over the normalized text; and +3. `context` becomes `{table_label_mac, row_path_mac, column_path_mac}` in the same way. + +Such an anchor can be verified, and its span shown, only over a copy of the paper the reader holds. + +## 6.4 Four kinds of anchor + +| Kind | Points at | Judged by | +| --- | --- | --- | +| Span | Part of a leaf's text: the anchor has a `span`. | The quote, then `node_hash`. | +| Leaf | A whole `sentence`, `cell`, `reference`, `authors`, `keywords`, `equation`, `equation-line`, `code` or `algorithm`. | `node_hash`. | +| Container with content | A `section`, `figure`, `panel`, `table`, `theorem` or `footnote`. | `own_hash`, with `node_hash` reported. | +| Container without content | Any other node. | Its ID and its leaves. | + +## 6.5 Resolution + +To resolve an anchor against a document's current state (its nodes, its ID table and its corrections): + +**Follow the ID.** +If the anchor's node is live, use it. +Otherwise follow the ID table: an alias leads to its node, a retirement to its successor, repeatedly, until a live node is reached, a deletion ends the chain, or an ID is unknown or repeats. +The anchor is *retired* when the chain passed a retirement; an alias alone does not retire it. +The kind is the anchor's `kind`, else the live node's, else the retired entry's `node_kind`. + +**Find the quote.** +The quote's hits in a text are the positions where `exact` occurs, or, for a hashed quote, where a window of `length` code points has that hash. +When there is more than one hit and the anchor has a prefix or suffix, keep the hits preceded by the prefix and followed by the suffix. + +**Judge**, by kind: + +| Kind | Current | Changed below | Moved | Reattached | Otherwise | +| --- | --- | --- | --- | --- | --- | +| Span or leaf | Not retired, and `node_hash` equal. | Never. | Retired, and the successor's text has exactly one hit (a span) or at least one (a leaf); a span takes the new position. | Not retired, changed, and exactly one hit, with the new position; or a changed node whose only changes since `rev` were `relabel` corrections, and whose own content with the earliest of those corrections' `from` label has the anchored `own_hash`. | Stale. | +| Container with content | Not retired, and `own_hash` and `node_hash` equal. | Not retired, `own_hash` equal, `node_hash` not. | Retired, and the successor's `own_hash` equals the anchored one. | Not retired, and only `relabel` corrections changed it, judged as for leaves. | Stale. | +| Container without content | Live and `node_hash` equal. | Live and `node_hash` not equal. | Retired, and the successor's leaves hold at least half of the anchored `leaves`, each matched by ID or else by `match_hash`. | Never. | Stale. | + +**The cell rule.** +A cell anchor whose ID led to no live node (a deletion, or an unknown ID), or whose successor fails the leaf rule, is reattached when exactly one cell in the document has the anchored `context` and exactly one hit of the quote. +This finds a value again even in a table with multi-level headers or row labels repeated across parameter sets. + +The result is `{result, node, node_hash?, span?, drift?, via?, reason?}`: the outcome, the live node and its `node_hash`, the new span, the drift of a `changed-below` result, the IDs followed, and a reason for `stale` and relabel results. +A `moved` or `reattached` anchor is re-pinned to the live node, and the move is recorded. + +Checks are stricter than readers: an extract is a span or leaf anchor and never accepts `changed-below`, because a check is about exact words. +`resolve.jsonl` resolves seventeen anchors made at revision 0 against `fixtures/packages/hale2026harmonic-damb` at revision 12, with every outcome. + +## 6.6 Drift + +`changed-below` must not last forever. +For a container *c* and an anchor made at revision *r*: + +1. The corrections that count are those with `index` greater than *r* whose `path` or `to_path` contains *c* and whose `touched` list is not empty. +2. `count` is their number, and *T* the union of their `touched` lists. +3. *L* is the set of leaves below *c* (including *c* itself if it is one) in the current state. +4. `share` is |*T*| divided by |*L* ∪ *T*|, written as a decimal with four places, rounded half up. +5. `level` is `none` when `count` is 0, `high` when `share` is greater than the threshold, and `low` otherwise. + +The threshold is a quarter by default; a project may set another ([20](20-projects.md)). +A reader shows a `high` drift as needing review. +A change to a section's heading changes its `own_hash`, so a rename is never mistaken for drift. diff --git a/spec/07-geometry.md b/spec/07-geometry.md new file mode 100644 index 0000000..e2d03de --- /dev/null +++ b/spec/07-geometry.md @@ -0,0 +1,64 @@ +# 7. Geometry + +## 7.1 Page fingerprints + +Several publishers stamp each download with the institution, date and time, so two copies of one paper rarely share a SHA-256. +Every page of a witness therefore also has a fingerprint, `scienting-page/1`. +Geometry and digitizations point at fingerprints, so a re-download keeps every box and every digitization. + +The input is the page's size after rotation, its text-layer lines in content-stream order (each a string and, where known, a box), and the SHA-256 of each embedded image's stream data as stored. +To compute the fingerprint: + +1. Remove every line that a stamp rule matches ([7.2](#72-stamp-rules)). +2. Join the remaining lines with U+0020. +3. Delete every whitespace character and every character of General Category Cc or Cf. +4. Fold Unicode script characters and dashes before digits as the strict projection does for text ([5.4](05-hashes.md#54-simple-notation)), then apply NFKC. +5. Round the width and height to whole points, half up. +6. The fingerprint is SHA-256 of the canonical JSON of `{"format": "scienting-page/1", "size": [width, height], "text": the text, "images": the image hashes, sorted}`. + +Whitespace is deleted rather than collapsed because text extractors disagree about where they insert spaces, and it is deleted before folding so that "10 -20" and "10-20" fold alike. +A scanned page with no text layer is fingerprinted by its size and its images alone. +Two witnesses whose fingerprints are equal, page for page, are the same edition of the paper. + +How lines are extracted from a PDF is outside this text; the vectors give the lines, so implementations are tested on the function. +`fingerprints.jsonl` gives two differently stamped downloads of one ACS-style page and of one Wiley-style page that share their fingerprints, a page with one changed digit that does not, and a scan. + +## 7.2 Stamp rules + +Stamp rules are published in `scienting-stamps/1` files. +Each rule has an `id`, a `pattern`, a `where` (`any`, or `margin` with a `margin` in points, default 36) and a note. +A rule matches a line when its pattern is found in the line's normalized text, with ASCII letters compared without case; a `margin` rule matches only lines whose box lies wholly within the margin of one edge. +Patterns use only syntax that ECMAScript and Python read alike: literals, `.`, `*`, `+`, `?`, `^`, `$`, classes and escaped punctuation. + +[registry/stamps/scienting-stamps-1.json](../registry/stamps/scienting-stamps-1.json) holds the published rules. +A team adds rules it learns, when two witnesses of one version differ only in such lines, in files of its own with `learned: true`. +A missed stamp splits one edition into two; an over-broad rule hides a real difference. + +## 7.3 `pages.jsonl` + +| Property | Holds | +| --- | --- | +| `witness` | The witness ID. | +| `page` | The page number in the witness, from 1. | +| `page_fp` | The fingerprint. | +| `size` | `[width, height]` in points, after rotation. | +| `page_label` | The printed page label, when there is one. | +| `text_layer` | Whether the page has a text layer. | +| `stamps_removed` | The IDs of the rules that removed lines, in line order, when any did. | + +Pages sort by witness ID, then page. + +## 7.4 `locations.jsonl` + +| Property | Holds | +| --- | --- | +| `node` | The node ID. | +| `page_fp` | The page's fingerprint, which some page of some witness has. | +| `page` | The page number. | +| `page_label` | The printed label. | +| `boxes` | One or more `[x0, y0, x1, y1]` in PDF points, origin at the top left after rotation. | +| `approx` | `true` when the boxes come from OCR line boxes rather than glyphs. | + +A node has one record per page it appears on; a sentence that wraps has several boxes. +Locations sort by the node's position in document order, then page, then fingerprint. +Because locations point at fingerprinted pages, a reader can rebuild a document from its own download: it fingerprints the pages, finds the matching ones and reads the text at the stored boxes. diff --git a/spec/08-fidelity.md b/spec/08-fidelity.md new file mode 100644 index 0000000..461e1bc --- /dev/null +++ b/spec/08-fidelity.md @@ -0,0 +1,161 @@ +# 8. Fidelity, receipts and spot-checks + +## 8.1 Levels of fidelity + +| Level | Meaning | +| --- | --- | +| F0 converted | One reading, not corroborated. | +| F1 resolved | Every suspect in the node was answered against the page image and passed the gate. | +| F2 corroborated | An independent witness agrees, by `match_hash` and complex keys, or the text is born digital, as a Typst or LaTeX source is. | +| F3 proofread | A named person compared the node with the page image, and a valid receipt they signed lists the node at its current `node_hash`. | + +Levels apply to leaves. +The pipeline records F0, F1 or F2 in a leaf's `fidelity`; F3 comes only from receipts. +A correction that changes a leaf drops it back: the gate's crop evidence makes it F1 at most, until it is corroborated or proofread again. + +## 8.2 Levels + +A leaf's level is the highest of its recorded `fidelity` and the levels of every valid receipt ([8.6](#86-receipt-status)) that lists it at its current `node_hash`. +A receipt at a lower level never lowers a node; only a revocation, a failed spot-check or a correction does. +A spot-check's `qa:` receipt ([8.8](#88-spot-checks)) raises the nodes it sampled, except those its `errors` name. +A document reports, in `document.json`, the lowest level among its leaves and the count at each level. + +## 8.3 Receipts + +A paper has thousands of nodes, and nobody signs thousands of times, so people sign receipts: one signature over a Merkle root of everything reviewed in a sitting. + +| Property | Required | Holds | +| --- | --- | --- | +| `format` | Yes | `scienting-receipt/1`. | +| `id` | Yes | The record ID ([4.6](04-identity.md#46-record-ids)). | +| `doc` | Yes | The document key. | +| `rev` | Yes | The revision reviewed. | +| `level` | Yes | `F1`, `F2` or `F3`. | +| `scope` | Yes | `all`, `section:<id>`, `page:<n>`, `targeted:<name>` (such as `targeted:lode`), or `qa:<receipt id>` for a spot-check. | +| `nodes` | Yes | `[[id, node_hash], …]`, sorted by ID without repeats. | +| `records` | No | `[[kind, id, hash], …]` for other things signed in the sitting: `annotation`, `digitization`, `correction`, `layer` or `checklist`. | +| `root` | Yes | The Merkle root ([8.5](#85-merkle-roots)). | +| `evidence` | Yes | What the reviewer looked at: `{kind, sha256, node?, page_fp?, box?, note?}` with `kind` `crop`, `witness` or `source-file`, or `{kind: "person", by}`. A regenerated crop is different evidence. | +| `by` | Yes | The signer's roster key. | +| `at` | Yes | When it was signed. | +| `qa` | For `qa:` scopes | The spot-check ([8.8](#88-spot-checks)). | +| `export_of` | No | The receipt this one re-issues under a keyed scheme. | +| `keyed` | No | The scheme its values are keyed under, when it leaves the team. | +| `signature` | Yes | `{scheme, key, value}` ([8.4](#84-record-hashes-and-signatures)). | + +A receipt lists nodes, records, or both. +A correction invalidates a receipt for the corrected node only, because the node's `node_hash` no longer matches; the rest still counts. + +A receipt shared outside the team cannot carry plain node hashes, which would leak short texts, and its signature covers them. +So an export re-issues it: a new receipt with `export_of`, values under the export's key, signed by the original reviewer or a team key with the `export` purpose. + +## 8.4 Record hashes and signatures + +A signed record's record hash is SHA-256 of the canonical JSON of the record without `id` and `signature`. +Its `id` is the 13-character letter-first encoding of that hash. +Its signing payload is the canonical JSON of `{"format": <the record's format>, "hash": <the record hash>}`. + +| Scheme | `value` | +| --- | --- | +| `ed25519` | The RFC 8032 signature of the payload, in standard Base64 with padding. | +| `ssh` | An SSH signature of the payload in the namespace `scienting`, armored. | +| `gpg` | A detached, armored OpenPGP signature of the payload. | +| `sigstore` | A Sigstore bundle for the payload, as JSON text. | +| `cose` | Reserved: a COSE_Sign1 message over the payload, in Base64, as the IETF SCITT work shapes signed statements, so other transparency services can verify a receipt. No vector yet. | +| `ml-dsa-65` | An ML-DSA-65 signature (FIPS 204, the pure variant with an empty context) of the payload, in Base64, for the decades after Ed25519 is no longer considered safe; the roster's `public` is the 1952-byte key in Base64. The reference implementation reproduces NIST's ACVP vectors; `signatures.jsonl` pins a key generation and a deterministic signature. | + +A consumer treats a record signed with a scheme it does not implement as invalid, so a reserved scheme can be adopted by a new minor version without any format changing. +`signature.key` is the signer's roster key and equals `by`. +Self-hosted deployments sign with team keys or a private Sigstore deployment; the public Sigstore instance, whose log permanently records each signer's identity, is for public layers only. +`signatures.jsonl` verifies one receipt and the RFC 8032 test vector. + +## 8.5 Merkle roots + +A receipt's items are `["node", id, node_hash]` for each listed node, in order, followed by its `records`. +The root follows RFC 6962: a leaf hash is SHA-256 of the byte 0x00 and the item's canonical JSON; an interior hash is SHA-256 of 0x01 and the two child hashes; a list of *n* > 1 items splits after the largest power of two less than *n*. +RFC 6962 has since been replaced by RFC 9162, which defines the same tree. +A root over one item is that item's leaf hash; a receipt with no items is invalid. +`merkle.jsonl` gives roots for one to seven items. + +The tree allows a proof that one node was covered without revealing the others. +An inclusion proof, `scienting-proof/1` with `kind` `inclusion`, holds the `receipt`, the `item`, its `index` among the receipt's items, the `size` of the tree, the `root` and the `path`: the audit path of RFC 9162 §2.1.3.1, as hex hashes, leaf-most first. +A verifier recomputes the root from the item's leaf hash and the path as RFC 9162 §2.1.3.2 describes and compares it with the receipt's root. +`proofs.jsonl` gives the path for every item of trees of one to seven items, and `fixtures/records/proof-inclusion.json` proves one node of the example paper's first receipt. + +## 8.6 Receipt status + +A receipt is: + +1. **invalid** when its root, ID or signature does not verify, or its signer's key was not valid when it was signed (`registered_at` ≤ `at` < `revoked_at`); +2. otherwise **revoked** when a valid revocation names it, or names its signer with a period that contains its `at`; +3. otherwise **suspended** when a valid spot-check of it found an error; +4. otherwise **valid**. + +Only valid receipts set levels. +A suspended receipt stays suspended; its reviewer reviews the sitting again and signs a new receipt, which needs its own spot-check. +A spot-check is itself a receipt, so its status may depend on its own spot-check; statuses are settled from the end of each chain, and the receipts of a chain that loops back on itself are invalid. + +## 8.7 Revocations and the roster + +A revocation, `scienting-revocation/1`, names one `receipt`, or a `signer` and a `period` `{from, to}`, with a `reason`, and is signed like a receipt. +It is valid when its signature verifies and its signer is the revoked receipt's signer, the signer it names, or a key whose `role` in the roster is `owner`. + +The roster, `scienting-roster/1`, lists the keys that may sign: each with an `id`, a `person`, a `role`, a `scheme`, its `public` key (Base64 for Ed25519 and ML-DSA-65), its `purposes` (`sign`, `spot-check`, `export`, or `witness` for a party that cosigns the team's log checkpoints, [23](23-log.md)), `registered_at` and `revoked_at`. +A key MAY carry its `did`, the `did:key` decentralized identifier the public key determines: `z` and the base58btc of the multicodec prefix (`0xed` for Ed25519, `0x1207` for ML-DSA-65, as varints) followed by the key bytes; a validator refuses a `did` that the key does not determine (`doc.roster.did`), so a signer can be named outside the store without a second name. +The `role` is the holder's role in the team that keeps the roster, `owner`, `editor`, `reader` or `guest`, as in a project ([20](20-projects.md)). +Because the roster carries it, a package that carries its roster carries everything needed to judge its revocations. +A package MAY carry the roster its receipts need as `roster.json`, so its receipts verify without the store. +The roster is meant to be the one a store verifies against; see the [rationale](../docs/rationale.md#known-limits). + +## 8.8 Spot-checks + +For each F3 receipt, a second reviewer checks a sample of its nodes and signs a `qa:` receipt. +A seed the reviewer controls could be ground, by varying the receipt until the sample falls on careful work, and a seed the checker controls could be ground by the checker, so the seed is a value neither can steer: + +1. The seed is the checker's VRF proof, under RFC 9381's ECVRF-EDWARDS25519-SHA512-TAI, for the input that is the canonical JSON of `{"format": "scienting-spot-check/1", "receipt": <the original's record hash>}`, made with an Ed25519 key registered in the roster with the `spot-check` purpose before the original was signed. + A verifiable random function has exactly one valid proof for a key and an input, where an Ed25519 signature has many, so the checker cannot try proofs until the sample suits, and the reviewer cannot predict the proof without the checker's private key. +2. The sample size is the smaller of *n* and the larger of `minimum` and ⌈`rate` × *n*⌉, for the original's *n* nodes; the defaults are a rate of `0.05` and a minimum of 10. +3. Rank the original's node IDs by the hexadecimal SHA-256 of the proof's VRF output, the 64 bytes `ECVRF_proof_to_hash` gives, followed by the ID's UTF-8, then by ID, and take the first ones. + +The `qa` object records `of`, `key`, `seed` (the 80-byte proof, Base64), `rate`, `minimum`, the `sample` sorted by ID, and the `errors` found, each `{node, kind?, note?}`. +A verifier checks the proof against the checker's public key and the input before it recomputes the sample. +`vrf.jsonl` pins the VRF on the RFC's own example and on the example paper's seed. +The `qa:` receipt's `nodes` are the sampled nodes at the hashes the original lists, its `scope` is `qa:` and the original's ID, every error names a sampled node, and it is signed at or after the original. +Anyone can recompute the sample; `spotcheck.jsonl` does. +The payload's identifier, `scienting-spot-check/1`, is registered with the other formats so that no file ever carries it by mistake; it names a signing payload, never a file. + +## 8.9 Reviewer error bounds + +One sample proves little; what someone relying on the work needs is a bound on each reviewer's error rate across all their samples. +With *k* errors in *n* sampled nodes, the bound is the one-sided Clopper–Pearson upper confidence bound at confidence *c*, by default 0.95: the rate *p* at which the probability of at most *k* errors in *n* is 1 − *c*, or 1 when *k* = *n*. +It is reported to six decimal places, rounded up. +With no errors the bound is about 3/*n*, so zero errors in 300 sampled nodes bounds a rate below 1%; `bounds.jsonl` gives cases. + +A QA report, `scienting-qa-report/1`, states for each reviewer who signed a delivery the nodes sampled, the errors found, the confidence, the method `clopper-pearson` and the bound. +It is the record a buyer keeps, so it is signed like a receipt ([8.4](#84-record-hashes-and-signatures)): `by` names the roster key of the team that made the delivery, `id` derives from the record hash, and `signature.key` equals `by`. + +## 8.10 Targeted F3 + +Most of a paper is never relied on, so a team proofreads the target set: the nodes its claims, data and quotations rest on. + +1. The anchored nodes: every live node that an extract, a dataset value, a confirmed `claim-link`, a draft quotation or a pinned citation anchors, each anchor resolved first ([6.5](06-anchors.md#65-resolution)). + An anchored leaf is a target; an anchored container contributes its leaves. +2. Every `equation` and `equation-line`. +3. Under the project's digit rule ([20](20-projects.md)): with `all`, every `sentence` and `cell` with a digit in a `text` or `math` run; with `anchored-sections`, only those in a section that holds an anchored node; with `none`, none. + Digits are characters of General Category Nd. + Digits in `cite`, `xref` and `fnmark` runs do not count, so citation marks, "Figure 3" and footnote marks pull nothing in. + A node's section is its nearest ancestor-or-self of kind `section`, or the `front` or `back` matter when it has none. + +The set is reported in document order, each node with the first reason that applies: `anchored`, `equation` or `digits`. +Neighbors shown for context are not in the set, and nothing new comes to rest on a node below F3 without the node joining the set. +`targets.jsonl` gives the set of `fixtures/packages/hale2026harmonic-damb` under each digit rule. + +## 8.11 Checklists + +An export of a document, such as accessible HTML, can be checked against a standard, and that check is a record a buyer keeps. +A checklist, `scienting-checklist/1`, holds the `doc` and `rev` checked; the `standard`, `{name, level?, url?}`, such as WCAG 2.1 at level AA; the `export` checked, `{kind, sha256, size?}`, so the record binds to one file; its `items`, each a `criterion`, its `result` (`pass`, `fail` or `not-applicable`), the `method` (`manual`, or `automated` with the `tool` and its version) and an optional `note`; and `by` and `at`. +Its content hash is SHA-256 of the canonical JSON of the record without `id`, and its `id` is the record ID of that hash ([4.6](04-identity.md#46-record-ids)). +A checklist carries no signature of its own: the person who checked signs a receipt that lists it as `["checklist", id, hash]` ([8.3](#83-receipts)), so one sitting covers a checklist together with the nodes read for it. +The receipt covers the checklist only at that hash, so a checklist changed afterwards is uncovered. +`fixtures/records/checklist/` holds a checklist for an accessible HTML export of the example paper and the receipt that covers it. +The format is `provisional` ([0.4](00-introduction.md#04-status)). diff --git a/spec/09-figures-tables-equations.md b/spec/09-figures-tables-equations.md new file mode 100644 index 0000000..b38a54c --- /dev/null +++ b/spec/09-figures-tables-equations.md @@ -0,0 +1,37 @@ +# 9. Figures, tables and equations + +## 9.1 Figures and panels + +A figure holds its panels, its caption and its notes. +A panel's own content is its label only. +Its image and region are evidence, not content: re-extracting the image at native resolution adds an asset and changes no hash. + +| Panel attribute | Holds | +| --- | --- | +| `image` | `{sha256, media_type, native, dpi?}`: the embedded image, at native resolution when the PDF holds one. | +| `crop` | `{sha256, media_type, dpi}`: a crop of the panel's region at a fixed resolution. | +| `figure_text` | `[{id, text, role, page_fp?, boxes?}]`: text found inside the panel, with `role` `axis-label`, `tick-label`, `legend`, `annotation` or `other`. | + +Text inside a figure is not prose and is not split into sentences. +Its items have IDs ([4.2](04-identity.md#42-minting-node-ids)) so that a digitization can anchor its axis labels to them. +A panel's region on the page is its location ([7.4](07-geometry.md#74-locationsjsonl)). + +## 9.2 Tables + +A table holds its caption, an optional head, one body and its notes. +Rows and cells are nodes, with all five values, so the gate, the hashes and the database treat them like any other node, and a cell is addressed like a sentence. + +Columns are defined in the table's `columns` attribute, each with an ID and a header path: the IDs of the header cells above it, outermost first. +Header text is stored once, in the header cells. +A row's `header_path` lists the cells that label it: a row-group header and the row's own header cell. +A cell records its column, its spans and its role; the expanded grid is derived, never stored. + +So inserting a row that a reading dropped adds a row node and changes no other row's or cell's ID or hash, and fixing a header cell changes that cell, not the table. +A table continued across pages is one table node; its pages are locations. +For people, a cell can be shown as "Table 2, row CT–CT, column K_r" from its header paths. + +## 9.3 Equations + +An equation keeps its source as written, `tex` from a conversion or `typst` from a draft, and its printed number as its `label`, so numbering never collides with a renderer's own. +An equation that the source numbers line by line (Eq. 3a) has `equation-line` children, each with its own label and source. +MathML is derived by a pinned tool and recorded, with the tool's name and version, in `derived/mathml.jsonl`. diff --git a/spec/10-references.md b/spec/10-references.md new file mode 100644 index 0000000..26df8e3 --- /dev/null +++ b/spec/10-references.md @@ -0,0 +1,15 @@ +# 10. References and citations + +Each reference is a `reference` node holding its printed runs, exactly as printed, and its printed number as its `label`. +`references.jsonl` holds, for each reference node in document order, a record with `node`, `label`, an optional parsed `csl` record in CSL-JSON, and its `resolution`: + +| Resolution | Means | +| --- | --- | +| `{type: "doi", doi}` | The reference names a DOI. | +| `{type: "document", doc}` | It names a document in the same store, by key. | +| `{type: "none"}` | Nothing yet. | + +Every `cite` run links a sentence to one or more references. +The citation graph is therefore sentence-level: for any reference, the format gives every sentence that cites it, which is the citation's context. +The database derives a `citations` table from the runs ([13](13-database.md)). +An article's references and its Supporting Information's are separate documents' references and never mix. diff --git a/spec/11-corrections.md b/spec/11-corrections.md new file mode 100644 index 0000000..522f3bf --- /dev/null +++ b/spec/11-corrections.md @@ -0,0 +1,82 @@ +# 11. Corrections + +A correction, `scienting-correction/1`, is an operation on an established document, with its evidence and its author. +Corrections are added and never edited, so a document's history is its original reading plus its corrections. +Each has an `index`, counted from 1 in the order corrections are applied, and the document's revision is the index of the last. + +## 11.1 Operations + +| `op` | Fields | Does | IDs | +| --- | --- | --- | --- | +| `replace` | `target`, `find`, `replace`, optional `run` | Replaces the one occurrence of `find` among the target's editable strings with `replace`, a string or, inside a text run, a list of runs. | Unchanged. | +| `insert` | `parent`, `place_after` (a sibling, or null for first), `node` | Adds a subtree: kinds, labels, attributes and content, with each equation run naming its child as `{"kind": "equation", "child": i}`. | New IDs, minted ([4.2](04-identity.md#42-minting-node-ids)). | +| `insert` | `target`, `run`, `offset`, `text` | Inserts text into one run of the target, at a code-point offset in that run's editable string. | Unchanged. | +| `delete` | `target` | Removes an artifact and its subtree, such as a running head read as text. | All retired, without successors. | +| `split` | `target`, `offset` | Splits a sentence at an offset in its plain projection, which falls between runs or inside a text run; whitespace at the split is removed from both parts, and each equation child goes with its run. | The first part keeps the ID; the second gets a new one. | +| `merge` | `target`, `with`, optional `joiner` | Joins a node with its next sibling of the same kind: the runs of two run-bearing nodes, with the joiner (default one space) between, or the children of two `paragraph`, `list`, `item`, `quote`, `caption`, `figure-note` or `table-note` nodes. | `with` is retired, with the target as successor. | +| `move` | `target`, `parent`, `place_after` | Changes reading order or containment. | Unchanged. | +| `reclassify` | `target`, `kind` | Changes a node's kind, such as a paragraph that is really a caption, to a kind with the same content shape. | Unchanged. | +| `relabel` | `target`, `label` | Changes a printed label. | Unchanged. | +| `set` | `target`, `attr`, `value` | Sets one structural attribute: a section's `level`, a table's `columns`, a cell's `column`, `rowspan`, `colspan` or `role`, a row's `header_path`, a list's `ordered`, an item's `marker` or a theorem's `variant`. | Unchanged. | + +A leaf's editable strings are the `text` of its `text`, `link`, `cite`, `xref` and `fnmark` runs and the `source` of its `math` runs, each searched on its own; an equation's `source`; a verbatim node's `text`. +`set` exists because readings drop spans, roles and header paths; see the [rationale](../docs/rationale.md#corrections). +Runs are made canonical after every operation, and the result MUST satisfy every rule of [3](03-nodes.md). + +## 11.2 Every correction records + +| Property | Holds | +| --- | --- | +| `evidence` | At least one item: `crop`, `witness` or `source-file` by SHA-256, or `person`. | +| `author` | `{key}` for a person in the roster, or `{model, run}` for a model's session, where `model` is `{name, provider?, version?, weights?, prompt?, parameters?, processor?}`: the model's name, who served it, its version, and SHA-256 of the weights, the instructions and the sampling parameters it ran with, as far as the team can obtain them, and where it ran ([14](14-rights.md)). | +| `reason`, `at` | Why, and when. | + +A proposal, such as one a tool makes, carries these and `status: "proposed"`, and no applied fields. + +## 11.3 Applied fields + +When a correction is applied, its record gains: + +| Property | Holds | +| --- | --- | +| `index`, `id` | Its position, and its record ID. | +| `before`, `after` | The target's `node_hash` before and after, or null; for an inserted subtree, `target` is its root. | +| `path` | The target's ancestors when it was applied, root first; for an insert, the new subtree's. | +| `to_path` | For a move, the new ancestors. | +| `touched` | The leaves whose content the correction changed, sorted: the target of a `replace`, text `insert`, `relabel` or `set` on a leaf; the new leaves of a node `insert`; the deleted leaves of a `delete`; both parts of a `split`; both nodes of a run `merge`, or the moved-in leaves of a container `merge`; the moved leaves of a `move`; the leaves of a reclassified node. | +| `created`, `retired` | IDs minted or retired. | +| `from` | The label, kind or attribute value before a `relabel`, `reclassify` or `set`. | + +Retirements are also entered in `ids.jsonl` with the correction's index as `rev`. +Drift ([6.6](06-anchors.md#66-drift)) is computed from `path`, `to_path` and `touched` alone, so it needs no replay. + +## 11.4 The gate + +A correction is refused, naming the rule ([22](22-conformance.md)), when: + +1. it does not match the correction schema, `schemas/correction.schema.json`; +2. a target, parent or sibling is not live, or the root would be deleted, moved, merged or reclassified; +3. `find` is empty or does not occur exactly once; +4. an `insert` has no crop evidence, or names a run or offset its target does not have; +5. a digit changes without crop evidence: in a `replace` whose `find` and replacement have different digits, a `delete` of leaves that hold digits, or a `relabel` whose labels have different digits; +6. any leaf outside `touched` has different digits afterwards; +7. a `split` falls outside the sentence, inside a run other than text, or leaves a part empty; +8. a `merge` joins nodes that differ in kind, are not mergeable, or are not adjacent siblings; +9. a `move` would put a node inside itself; +10. a `reclassify` changes the content shape, or a `relabel` or `set` targets a kind that does not take it; or +11. the result breaks a rule of [3](03-nodes.md). + +The gate needs only the document's current state, so a tool can run it on a proposal before applying anything, and get back the record the correction would append or the rule it breaks. +`tools/validate.py --correction` does this against a package. + +Digits are characters of General Category Nd in the plain projection. +A package's corrections are also checked as a whole: indexes run from 1 without gaps, each `id` derives from its record, `rev` equals their number, every retired ID is in `ids.jsonl`, and the last correction of each leaf ends at its current `node_hash`. +`corrections.jsonl` in the vectors applies each operation, and each refusal, to a small document. + +## 11.5 The history root + +`document.json` carries `history`: the root of the tree of [8.5](08-fidelity.md#85-merkle-roots) whose items are `["correction", index, id]` for each correction in order, or SHA-256 of the empty string when there are none, which is how RFC 9162 hashes the empty tree. +Because corrections are only appended, a consistency proof (RFC 9162 §2.1.4) between the roots at two revisions shows that the later history extends the earlier one rather than rewriting it. +The proof is a `scienting-proof/1` with `kind` `consistency`, holding the `doc`, `from_rev`, `to_rev`, `from_root`, `to_root` and the `path` as hex hashes; a verifier applies RFC 9162 §2.1.4.2. +A checks-only package carries no corrections, so its history is the empty root. +`proofs.jsonl` gives consistency proofs for every prefix of small trees and for the example paper between revisions 8 and 12; `fixtures/records/proof-consistency.json` is the latter. diff --git a/spec/12-package.md b/spec/12-package.md new file mode 100644 index 0000000..b7d6cf0 --- /dev/null +++ b/spec/12-package.md @@ -0,0 +1,71 @@ +# 12. The package + +A document travels as a package: a folder named by its key, or the same folder zipped. + +## 12.1 Files + +| Path | Required | Holds | +| --- | --- | --- | +| `MANIFEST.json` | Yes | The manifest ([12.3](#123-the-manifest)). | +| `document.json` | Yes | The document ([2.2](02-model.md#22-documentjson)). | +| `nodes.jsonl` | Yes | Every node, in document order ([3](03-nodes.md)). | +| `witnesses.json` | Yes | Every witness, with its rights ([2.3](02-model.md#23-witnessesjson)). | +| `provenance.json` | Yes | Tools and versions, backends, cached readings, stages and where each ran. | +| `pages.jsonl` | No | Every page of every witness ([7.3](07-geometry.md#73-pagesjsonl)). | +| `locations.jsonl` | No | Geometry per node and page ([7.4](07-geometry.md#74-locationsjsonl)). | +| `references.jsonl` | No | Parsed references and their resolution ([10](10-references.md)). | +| `corrections.jsonl` | No | Every correction, in order ([11](11-corrections.md)). | +| `receipts.jsonl` | No | Receipts and revocations, sorted by `at` and then `id` ([8](08-fidelity.md)). | +| `ids.jsonl` | No | Retired IDs and legacy aliases ([4.4](04-identity.md#44-idsjsonl)). | +| `suspects.jsonl` | No | Unresolved suspects, sorted by `id` ([5.7](05-hashes.md#57-suspects)). | +| `roster.json` | No | The roster its receipts need ([8.7](08-fidelity.md#87-revocations-and-the-roster)). | +| `assets/` | No | Images and crops, as `<sha256>.<extension>`, present or listed only. | +| `datasets/<id>/` | No | Datasets ([15](15-datasets.md)). | +| `derived/` | No | Rebuildable renderings, never authoritative ([12.7](#127-derived-files)). | + +An optional JSON Lines file with no records is omitted. +Every file is in the canonical form of [1.9](01-conventions.md#19-files). + +## 12.2 Paths + +Paths use `/`, are relative, have no empty, `.` or `..` segment, no backslash and no NUL, and are already normalized. +No two paths are the same once case-folded, so a package reads alike on every file system. +A package folder carries no symbolic links, and a consumer refuses one that does, as it refuses a package whose files exceed its own size limit. +In a zip, entries are UTF-8 named, sit under one top-level folder named by the key, are stored or deflated, carry no symbolic links, and are unique; a consumer refuses an archive that breaks any of these, or whose expanded size exceeds its own limit. +A producer that wants byte-identical archives writes entries sorted by path, dated 1980-01-01 00:00, with no extra fields; `fixtures/packages/tiny2026tiny-j4qm.sct.zip` is such an archive. + +## 12.3 The manifest + +`MANIFEST.json`, `scienting-package/1`, is `{format, doc, key, files}`: the package format, `scienting-doc/1`, the document key, and every other file as `{path, sha256, size}`, sorted by the UTF-8 bytes of the path. +An asset whose bytes stay in the asset store is listed with `present: false`; nothing else may be. +The SHA-256 of `MANIFEST.json` pins the whole package. + +## 12.4 Provenance + +`provenance.json` holds `tools` (`{name, version}`), and optionally `backends`, `readings` (each cached reading's ID, witness, backend and SHA-256), `stages` (each stage's name, tool, input hashes, output hash, the `processor` where it ran, and the uses it ran under) and a `session`. +Every stage that uses a model or an outside service records where it ran ([14](14-rights.md)). + +## 12.5 Text policies + +| Policy | Means | +| --- | --- | +| `full` | Every leaf keeps its content. | +| `checks-only` | Every leaf has `withheld: true` and no `content`; panels drop their figure text; references keep their resolution but no CSL; there are no corrections, suspects or datasets; and the hashing scheme is keyed: `hmac-team` between the team's machines and `hkdf-pages` outside the team ([5.8](05-hashes.md#58-keyed-hashes)). | + +A checks-only package is how a team shares its annotations on a paywalled paper without sharing the paper. +Its text lives in the team's private asset store, and only key holders can check its values. +`fixtures/packages/hale2026harmonic-damb.checks-only` is such an export of `hale2026harmonic-damb` to another machine of the team, under the team key in `fixtures/keys/`. + +## 12.6 Assets + +Assets are named by SHA-256, so every read is rehashed and a regenerated crop is a different asset. +Bytes that live only in the asset store are listed in the manifest with `present: false`, with their size. + +## 12.7 Derived files + +`derived/` holds what a pinned tool makes from the package, such as `derived/mathml.jsonl`, whose lines are `{node, run, tool, mathml}` with `run` null for an equation node. +Nothing derived is content, and a consumer may delete and rebuild it. + +## 12.8 Media type and extension + +A zipped package has the extension `.sct.zip` and the media type `application/vnd.scienting.doc+zip`. diff --git a/spec/13-database.md b/spec/13-database.md new file mode 100644 index 0000000..42a7cbe --- /dev/null +++ b/spec/13-database.md @@ -0,0 +1,62 @@ +# 13. The database form and the bundle + +## 13.1 Portability + +[sql/doc.sql](../sql/doc.sql) defines the document tables and [sql/store.sql](../sql/store.sql) a team store's tables. +Both run unchanged on SQLite, Dolt and PostgreSQL, under these rules: + +1. No foreign keys; references are checked by validators, not by the database. +2. Enumerations are `VARCHAR` with `CHECK (… IN (…))`. +3. JSON values are canonical JSON in `TEXT` columns; booleans are `INTEGER` 0 or 1. +4. Every table has a primary key, and key columns are `VARCHAR` with a length, as MySQL-compatible engines require. +5. No table, column or index is named with a word reserved in SQLite, PostgreSQL or MySQL; so the formats' `key`, `index`, `at`, `by`, `before` and `after` are `doc_key`, `idx`, `made_at`, `signer`, `before_hash` and `after_hash`. + +## 13.2 Tables + +| Table | One row per | Notes | +| --- | --- | --- | +| `works` | work | Its key and `same_as`. | +| `documents` | document | Every property of `document.json` as a column, plus `provenance`, `roster` and `package_hash`. | +| `witnesses` | witness | With `ord`, its position in `witnesses.json`. | +| `nodes` | node | With `seq`, its position in document order. | +| `pages`, `locations`, `refs` | page, location, reference | | +| `corrections` | correction | The common properties as columns; the rest in `details`. | +| `node_ids` | retired ID or alias | | +| `receipts`, `revocations` | receipt, revocation | | +| `suspects` | suspect | | +| `package_files` | asset, dataset file or derived file | Its path, SHA-256, size and whether its bytes were present. Bytes go to the asset store. | +| `citations` | cite run and reference | Derived on load. | +| `receipt_nodes` | node a receipt lists | Derived on load. | + +A 30-page paper is about 3,000 nodes, so 500 documents are about a million and a half rows, which SQLite and Dolt hold comfortably. + +## 13.3 Load and unload + +Loading a package is a pure function of the package: each record becomes a row, an optional property absent from the record is NULL, and JSON-valued properties are stored as canonical JSON. +Unloading writes each file back from its rows in the file's defined order, omitting optional properties that are NULL and optional files that have no rows, copies the other files from the asset store, and writes the manifest. +Unloading gives the package back byte for byte, and its manifest hash with it; the suite checks this for every fixture. + +## 13.4 The store tables + +`store.sql` adds what a team adds to its documents: `roster_keys`, `projects`, `members`, `project_documents`, `reading_paths`, `layers`, `annotations`, `annotation_targets` (derived, so a reader finds the annotations on a node), `datasets`, `dataset_values`, `digitizations`, `views`, `policies`, `submissions` and `grades`. +Each keeps its record whole in a `record` or `descriptor` column, with the columns a query needs beside it. + +## 13.5 The bundle + +A bundle, `scienting-bundle/1`, is one SQLite file that a reader or a server queries. +It holds the tables of `doc.sql` and `store.sql`, then those of [sql/bundle-sqlite.sql](../sql/bundle-sqlite.sql): + +| Table | Holds | +| --- | --- | +| `bundle_meta` | `name` and `value` pairs: at least `format` (`scienting-bundle/1`), `store`, `built_from` (the store revision) and `spec` (the version of these specifications). | +| `search` | An FTS5 index with one row per sentence, cell, equation outside a sentence and figure-text item, in document order: the document, the node, the unit, the context and the text. Withheld text is never indexed. | +| `embeddings_meta` | Reserved for embeddings with `sqlite-vec`: the model, its dimensions, and the rights use they were made under. | + +A search row's `unit` is `sentence`, `cell`, `equation` or `figure-text`. +For a node, `context` is the kind of its parent, such as `paragraph`, `heading`, `caption` or `row`, and `text` is its normalized plain projection ([3.6](03-nodes.md#36-the-plain-projection)). +An equation inside a sentence is searched as part of that sentence, so it has no row of its own. +A figure-text item names its panel as the node, its `role` as the context and its normalized `text` as the text. + +At team scale this is all the search a team needs. +A team can download its bundle and use it offline. +Because a bundle holds text, it is served only under the rights of [14](14-rights.md), checked again whenever text is served. diff --git a/spec/14-rights.md b/spec/14-rights.md new file mode 100644 index 0000000..cbcff35 --- /dev/null +++ b/spec/14-rights.md @@ -0,0 +1,61 @@ +# 14. Rights + +What a team may do with a paper depends on how it holds the paper, and AI processing is now a use that licenses name. +Every witness carries a rights record, every stage declares the uses it needs, and a stage runs only when the rights allow them. +Nothing here is legal advice: the defaults are a starting point that each team reviews with its own counsel. + +## 14.1 The rights record + +`scienting-rights/1`: + +| Property | Holds | +| --- | --- | +| `license` | The license as stated, `{spdx?, text?, url?}`, or null. | +| `basis` | How the team holds the right: `open-license`, `publisher-tdm`, `collective-license`, `subscription`, `own-work`, `permission` or `unknown`. | +| `uses` | Each of `read`, `tdm`, `redistribute`, `quote-public` and `accessible-copy` as `true`, `false` or `"unknown"`, and `ai`: a map from each pair `<purpose>/<processor>` to the same values. | +| `asserted_by` | `{by, evidence}`: who or what recorded the basis, and on what: a license URL, a contract's hash, Crossref's license field, a delivery, a statement. | +| `at`, `valid_until` | When it was recorded, and when the basis ends, or null. | + +Purposes are `internal` (results stay inside the organization) and `external` (results leave it). +Processors are `local` (the team's machines), `tenancy` (the team's cloud account), `outside-no-retention` (an outside service contractually keeping nothing) and `outside` (one that may retain). +A use or pair that is absent is `"unknown"`. +A producer sets `license` and a provisional `basis` from Crossref for open-access papers, and never sets a use to `true` on its own for anything else. + +## 14.2 Effective uses + +To find a witness's uses at a time *t*: + +1. If `valid_until` is set and *t* is not before it, every use is `false`: an expired basis stops everything at once. +2. Otherwise start from the record's uses, and for each policy that applies at *t*, replace each `"unknown"` with the policy's value, where the policy has one. + A policy never overrides `true` or `false`. + +A policy, `scienting-policy/1`, is a project owner's signed decision: `applies_to` (any of `basis`, `license`, `doi_prefixes` and `witnesses`, all of which must match), the `uses` it decides, a `statement`, `by`, `at` and `valid_until`. +It applies from `at` until `valid_until`. + +A node established from several witnesses takes the most restrictive of their uses: `false` if any is false, else `"unknown"` if any is unknown, else `true`. +This is the default combining rule. + +## 14.3 Stages + +`scienting-stages/1` maps each stage to what it needs: a list of `uses`, and optionally `ai`, with a `purpose` and the `processors` it may run on. +A stage may run on a processor when every listed use is `true`, the processor is among those allowed, if any are listed, and the pair `ai/<purpose>/<processor>` is `true`. +When a check fails, the refusal lists what is lacking: a use or pair that is `false` by name, one that is unknown with a trailing `?`, and a disallowed processor as `processor:<name>`. + +[registry/stages/scienting-stages-default.json](../registry/stages/scienting-stages-default.json) holds a default set; a team replaces the file, not the code. +Rights are checked when a stage runs and again whenever text is served. +Every derived artifact records the rights record and use it was made under, so it can be listed and purged when a basis ends. + +## 14.4 Backends and profiles + +A backend's code and weights can be licensed differently, and the weight license may exclude commercial or competing use. +`scienting-backend/1` declares a backend's `code_license`, its `weights` with their licenses, and the `conditions` they impose: + +| Condition | Met when the team profile | +| --- | --- | +| `revenue-cap` with `usd` | states revenue or funding at most `usd`. | +| `no-competition` with `vendor` | states what it competes with, and that does not include the vendor. | +| `purpose` with `allowed` | states a purpose among those allowed. | + +`scienting-profile/1` records what conditions ask: the team's `purpose` (`research`, `personal`, `education`, `startup` or `commercial`), `revenue_or_funding_usd` as `{at_most}` or null when unknown, and `competes_with`, or null when unknown. +A condition whose answer is unknown is not met, and the gate refuses a backend with any unmet condition. +`rights.jsonl` exercises stages, policies, expiry, combining and backends. diff --git a/spec/15-datasets.md b/spec/15-datasets.md new file mode 100644 index 0000000..be6e44d --- /dev/null +++ b/spec/15-datasets.md @@ -0,0 +1,27 @@ +# 15. Datasets + +A dataset, `scienting-dataset/1`, is a Frictionless Data Package (`datapackage.json` with CSV or Parquet resources) with three additions. + +| Addition | Meaning | +| --- | --- | +| Units | Every numeric field has a `unit`, a string Pint can parse, so a checker can test dimensions. | +| Uncertainty | A field may give `uncertainty`: `{field?, kind}`, the field that holds it and its kind, `sd`, `se`, `resolution` or `unknown`. | +| Origin | Each resource has an `origin`, or `origin_field` and `origins` when it varies by row. | + +| Origin | Holds | +| --- | --- | +| `reported` | Values anchored to the table cells or sentences that print them, in `anchors.jsonl`. | +| `digitized` | Values read off a figure: the digitization's ID, and `anchors.jsonl` naming each value's series and point. | +| `computed` | A claim's implementation, by claim and pin. | +| `measured` | The team's own data, with its provenance. | + +The descriptor also carries `format` and an `id`, `ds-` and a key. +Each line of `anchors.jsonl` names a `resource`, a `row` (by primary key) and a `field`, and either an `anchor` or a `digitization`, `series` and `point`. +A value or row is addressed as `ds-…/<row>/<field>`. + +Values keep their digits as printed: CSV cells are never reformatted, and in JSON values are strings, so `1.526` and `1.5260` stay different. +A digitized value never passes as reported, and its uncertainty is at least the resolution of its digitization. + +A dataset's content hash is SHA-256 of the canonical JSON of `{"format": "scienting-dataset/1", "files": [[path, sha256, size], …]}` over its files, sorted by path. +A dataset can be a source of kind `dataset`, so a claim can rest on a value read from a figure, with that fact visible in its evidence. +`fixtures/packages/hale2026harmonic-damb/datasets/ds-hale-bond-params` reports Table 1, and the suite checks that every value resolves to the cell that prints it. diff --git a/spec/16-digitization.md b/spec/16-digitization.md new file mode 100644 index 0000000..093b09a --- /dev/null +++ b/spec/16-digitization.md @@ -0,0 +1,18 @@ +# 16. Digitization records + +A digitization, `scienting-digitization/1`, says how numbers were read off a figure panel, completely enough to repeat. + +| Part | Holds | +| --- | --- | +| `target` | The panel's `anchor`, and the `region` read, as a box on the page given by `page_fp`, with the witness's SHA-256 as evidence; or, for a figure that exists only as an image, the image's SHA-256 with the region in its pixels. | +| `axes` | For each axis: its `scale` (`linear`, `log`, `reciprocal` or `date`), `unit`, at least two `calibration` points from page coordinates to value, an optional third `check`, and its `label` anchored to the panel's figure text. | +| `series` | For each series: its legend, its mark (color, marker, line), its kind (`points`, `line`, `bars`, `error-bars` or `region`) and its values: each a position, a value, and an uncertainty from the image's resolution, the marker's size and the calibration's residual. | +| `method` | `manual`, `traced` or `proposed` (by a model), with the tool and its version. | +| `verification` | The overlay check: the image of the values re-plotted under the calibration, by SHA-256, and the mean and largest residual. | +| `confirmation` | The receipt of the person who confirmed it after seeing the overlay, or null. | +| `dataset`, `rev` | The dataset it yields, and the revision it was made at. | + +Calibration and values are in page coordinates, not an image's pixels, so a digitization does not depend on the raster it was done on. +A digitization stays current while the document has a page with its `page_fp` and its panel anchor is not stale. +A teammate's re-download, stamped differently, has the same fingerprints, so the digitization stays current on it; a different edition or region has a different fingerprint, so a swapped image never passes. +A digitization counts only when a person confirms it: a receipt with the record `["digitization", id, hash]`, where the hash is SHA-256 of the record without `confirmation`. diff --git a/spec/17-views.md b/spec/17-views.md new file mode 100644 index 0000000..bbf0bc5 --- /dev/null +++ b/spec/17-views.md @@ -0,0 +1,8 @@ +# 17. Views + +A view, `scienting-view/1`, is a Vega-Lite specification whose `usermeta.scienting` pins its data: `{format, id, data, computation?}`. +Each entry of `data` names a Vega-Lite data source, the dataset it is, the dataset's content hash and a resource, and the specification refers to it as `{"data": {"name": …}}`. +A view is declarative JSON, so it is diffable, renders without custom code, and is easy for a model to write. + +A view can also hold a computation: a claim's implementation, by claim and pin, run in the browser, with Vega-Lite parameters bound to its inputs. +That is how a reader drags a bond constant and watches the energy curve change beside the equation that defines it. diff --git a/spec/18-layers.md b/spec/18-layers.md new file mode 100644 index 0000000..1ee877b --- /dev/null +++ b/spec/18-layers.md @@ -0,0 +1,63 @@ +# 18. Layers and annotations + +Everything people and models add to a document is an annotation, and annotations are grouped in layers. +`scienting-layer/1` is the W3C Web Annotation Data Model with the anchor as a selector, so any Web Annotation tool can read it. +The JSON-LD context is [context/scienting-1.jsonld](../context/scienting-1.jsonld), published at `https://paperspec.scient.ing/context/scienting-1.jsonld`. + +## 18.1 One rule decides what is a claim and what is a layer + +If a statement is true independently of this paper, it belongs in a claim store as a claim, where it is checked and leveled. +If it is about reading this paper, it belongs in a layer, where it is attributed and signed but not checked. + +## 18.2 The layer + +A layer is a folder with `layer.json` and `annotations.jsonl`. +`layer.json` is an `AnnotationCollection` with the two contexts, `format`, an `id` of the form `tag:scient.ing,2026:layer:<store>/<record id>`, a `label`, a `purpose`, an `audience` (`novice`, `student`, `expert` or `mixed`), a `visibility` (`private`, `team` or `public`), a `license` (CC BY 4.0 by default when public), its `creator`, `created`, its `project`, the `docs` it annotates and its `total`. +A reader turns layers on and off, and the audience dial picks the level of glosses. + +## 18.3 The annotation + +Each line of `annotations.jsonl` is a W3C `Annotation`: + +| Property | Holds | +| --- | --- | +| `@context` | `["http://www.w3.org/ns/anno.jsonld", "https://paperspec.scient.ing/context/scienting-1.jsonld"]`. | +| `id` | `tag:scient.ing,2026:annotation:<store>/<record id>` ([4.6](04-identity.md#46-record-ids)). | +| `type`, `layer` | `Annotation`, and the layer's ID. | +| `motivation` | A W3C motivation: `commenting`, `describing`, `linking`, `questioning`, `assessing`, `replying` and the others. | +| `creator`, `created`, `modified` | An agent `{id, type, name}`, with `type` `Person` or `Software`, and times. | +| `body` | One body ([18.4](#184-bodies)). | +| `target` | A `SpecificResource` whose `source` is `tag:scient.ing,2026:doc:<store>/<key>` and whose `selector` lists an `AnchorSelector` holding a `scienting-anchor/1`, optionally followed by a W3C `TextQuoteSelector` for tools that do not know ours; or, for a reply, a `SpecificResource` whose source is another annotation. | +| `status` | `proposed`, `confirmed`, `rejected` or `withdrawn`. A model's annotation is `proposed` until a person confirms it. | +| `receipt` | For a confirmed annotation, the receipt that covers it. | + +The `TextQuoteSelector`, when present, repeats the anchor quote's `exact`, `prefix` and `suffix`, with an empty string for a `prefix` or `suffix` the quote lacks. +It is present only when the anchor's quote is plain text; an anchor whose quote is hashed or keyed ([6.3](06-anchors.md#63-keyed-anchors)) has none, so the fallback never shows text the anchor withholds. + +An annotation's content hash is SHA-256 of the canonical JSON of the annotation without `status`, `receipt` and `modified`. +A confirmed annotation is covered by its confirmer's receipt, which lists `["annotation", <record id>, <content hash>]`. +Replies are annotations that target annotations, so discussions are threads anchored to sentences. + +## 18.4 Bodies + +| `kind` | W3C type | Adds | Says | +| --- | --- | --- | --- | +| `gloss` | `TextualBody` | `audience` | An explanation at `novice`, `student` or `expert` level. | +| `claim-link` | `SpecificResource` | `source` (`lode:<tag>`), `pin`, `role` | That the span `states`, `uses` or `disputes` a claim. | +| `symbol` | `SpecificResource` | `source`, `pin`, `symbol` | That this occurrence of a symbol is a symbol claim. | +| `comment` | `TextualBody` | | A remark, opinion or interpretation. | +| `caveat` | `TextualBody` | | A warning a reader should see. | +| `question` | `TextualBody` | `for` | A question for a `reader`, a `group` or the `authors`. | +| `exercise` | `TextualBody` | `exercise` | A task with a key and a rule ([19](19-exercises.md)). | +| `citation-context` | `TextualBody` | `reference`, `verdict`, `reason` | Why a sentence cites a reference, and whether it supports it. | +| `prerequisite` | `SpecificResource` | `source` | What to read or know first. | +| `crosslink` | `SpecificResource` | `source`, `selector` | That the span corresponds to a span in another document. | +| `translation` | `TextualBody` | `language` | The span in another language. | +| `description` | `TextualBody` | `role` | A description of a figure, panel or table for readers who cannot see it: `alt`, a short text equivalent, or `long`, a full description. | +| `generated` | `TextualBody` | `generator` | Text a model wrote about the span; never mistaken for source. `generator` is `{model, run}` as a correction's model author is ([11.2](11-corrections.md#112-every-correction-records)). | + +A textual body has a `value`, and optionally a `format` (`text/plain` or `text/markdown`) and a `language`. +Nothing a model writes is ever stored as source text. +A model may propose a `description`, and like any annotation it stays `proposed` until a person confirms it; an accessible export uses confirmed descriptions only, and a figure with none has no description. +Other text a model writes about a span, such as a summary, is a `generated` annotation, which names its `generator`. +`fixtures/records/layer/` holds a layer with one annotation of each common kind and the receipt that confirms some of them. diff --git a/spec/19-exercises.md b/spec/19-exercises.md new file mode 100644 index 0000000..0b7a30d --- /dev/null +++ b/spec/19-exercises.md @@ -0,0 +1,43 @@ +# 19. Exercises, submissions and grades + +Because every sentence and cell has a permanent address, the answer to a verification exercise is an address, and an address can be graded. +The three formats of this chapter, exercise, submission and grade, are `provisional` ([0.4](00-introduction.md#04-status)): no course has used them yet, and the first that does will shape them. + +## 19.1 Exercises + +An exercise is an annotation of kind `exercise` whose `exercise` property holds a `scienting-exercise/1`: an `exercise` kind, a `prompt`, a `key` and a `rule`. + +| Kind | The student | The key | +| --- | --- | --- | +| `anchor` | Finds the sentence or cell that supports a statement. | `elements`: each a set of acceptable anchors, with points and feedback. | +| `check` | Decides whether a cited passage supports the citing sentence, and anchors the passage. | A `verdict` with points, and `elements`. | +| `trace` | Follows a value back to its original measurement. | A `chain`: an element per link, in order. | +| `reproduce` | Digitizes a plot and recomputes a value. | A `value`, a `tolerance`, a `unit`, the confirmed `digitization` it comes from, and points. | +| `verify` | Checks a model's `summary`, written with addresses, in which errors were planted. | `errors`: each a set of anchors and the correct verdict, with points. | + +The rule's `match` is `same-node` (the student's anchor resolves to the node a key anchor resolves to), `overlap` (and, where the key has a span, the student's span covers at least `min_overlap` of it; default `0.5`), or `chain` (each link matches in order, with credit per link). +Feedback is `{hit, miss}` per element. + +## 19.2 Verdicts + +| Verdict | Means | As claim evidence, if a person confirms it | +| --- | --- | --- | +| `supports` | The passage says what the citing sentence claims. | `supports` | +| `partly` | It says some of it, or with a qualification the citing sentence drops. | `qualifies` | +| `does-not` | It does not say it, or says the opposite. | `disputes`, or no record when merely irrelevant; the reviewer chooses. | +| `cannot-tell` | The passage, or the student's access to it, is not enough. | No record. | + +## 19.3 Submissions + +A submission, `scienting-submission/1`, holds the exercise's ID, the document and revision, a pseudonymous `student` ID, and `answers`: `anchors`, a `verdict`, a `chain` of anchor lists, a `value`, or `flags` (each an anchor and a verdict), as the kind needs. +The student's name never enters a submission; the mapping from pseudonym to student stays in the course's records. + +## 19.4 Grading + +Before grading, every anchor in the key is resolved, and if any is stale nothing is graded with it. +Each element of the key earns its points when any of the student's anchors matches any of its anchors under the rule; a `check` earns its verdict's points when the verdicts are equal; a `reproduce` earns its points when the value is within the tolerance; a `verify` earns an error's points when a flag matches it with the correct verdict. +Points are decimal strings, summed exactly. +The result is a `scienting-grade/1`: the submission, the exercise, the `score`, the `max`, and an item per element with its points, its maximum and its feedback. +`grading.jsonl` grades a hit, a miss and an overlap. + +Student submissions are educational records, so they live in the course's private store, never on a public log. diff --git a/spec/20-projects.md b/spec/20-projects.md new file mode 100644 index 0000000..c2ce452 --- /dev/null +++ b/spec/20-projects.md @@ -0,0 +1,17 @@ +# 20. Projects + +A project, `scienting-project/1`, is the unit a team works in. + +| Part | Holds | +| --- | --- | +| `key`, `store`, `name`, `description` | Its identity. | +| `members` | People with a `role` (`owner`, `editor`, `reader` or `guest`) and the roster keys they sign with. | +| `documents` | The project's documents, each with the `reason` it is included, `tags`, and a reading `status` per member: `unread`, `reading` or `read`. | +| `paths` | Reading paths: ordered steps through documents, nodes, claims and layers, for onboarding a student or preparing a reading group. | +| `layers`, `datasets`, `views`, `drafts` | What the project holds. | +| `claims` | The claim namespace or bundle it uses, as the `lode` setting. | +| `settings` | The digit rule for targeted F3 ([8.10](08-fidelity.md#810-targeted-f3)), the drift threshold ([6.6](06-anchors.md#66-drift)), the spot-check rate and minimum ([8.8](08-fidelity.md#88-spot-checks)), what happens when a right is unknown (`refuse`, the default, or `warn`), the stage requirements in use, as the `id` of their stage file ([14](14-rights.md)), and the project's transparency `log`: its `origin`, the roster keys that `witness` it, and the `threshold` of witnesses a checkpoint needs ([23](23-log.md)). | + +Projects are small on purpose: everything about them is designed for hundreds of documents, not millions. +Owners sign policies ([14.2](14-rights.md#142-effective-uses)). +Who may revoke receipts follows the roster instead: a key whose `role` in the roster is `owner` ([8.7](08-fidelity.md#87-revocations-and-the-roster)), so a project's owners hold keys with that role. diff --git a/spec/21-drafts.md b/spec/21-drafts.md new file mode 100644 index 0000000..5ac045a --- /dev/null +++ b/spec/21-drafts.md @@ -0,0 +1,17 @@ +# 21. Drafts + +A draft is a document of kind `draft`, established from a Typst project as a born-digital witness, so every sentence is F2 from the start. +Its sentences cite library sentences by address, in `xref` runs whose targets are addresses in other documents, and its works in `cite` runs whose references resolve to documents. + +## 21.1 The snapshot + +A snapshot, `scienting-snapshot/1`, is to a Typst draft what a lock file is to a document: a pinned, verified file the compile reads, so a draft renders offline and reproducibly. +It holds the `store`, when it was made, the `quotes` the draft cites (each an address, an anchor, the text, its fidelity and how the anchor resolved), the `claims` (each a reference and pin, with whatever renderings the draft uses) and the `datasets` (each an ID and content hash). + +## 21.2 Sentence IDs in a draft + +Authors rewrite constantly, and IDs must survive without cluttering the source. +IDs live in a sidecar, `ids.jsonl` in the Typst project, `scienting-draft-ids/1`: one line per sentence with its `id`, its `text_hash`, its `section` and its `ord`, and `pinned` when the author fixed the ID to a label. +Each conversion aligns the new sentences with the previous revision, exact text first and then by edit distance within the section; an edited sentence keeps its ID and gets a new hash, so its annotations reattach or go stale as [6.5](06-anchors.md#65-resolution) says. + +Both formats are `provisional` ([0.4](00-introduction.md#04-status)). diff --git a/spec/22-conformance.md b/spec/22-conformance.md new file mode 100644 index 0000000..de097f5 --- /dev/null +++ b/spec/22-conformance.md @@ -0,0 +1,56 @@ +# 22. Conformance + +## 22.1 The suite + +| Path | Holds | A conforming implementation | +| --- | --- | --- | +| `vectors/*.jsonl` | Inputs and expected outputs, one case per line. | Computes every expected output from its input. | +| `fixtures/packages/` | Valid packages: a converted chemistry paper with corrections, receipts, a multi-level-header table and a dataset; its checks-only export; an open-access paper with two witnesses; a Typst draft; a tiny document, as a folder and as the zip of [12.2](12-package.md#122-paths). | Accepts each, and recomputes every value it contains. | +| `fixtures/records/` | A valid record of every other format that is a JSON file of its own; the stage requirements and stamp rules are in `registry/`, and a bundle is built by `tools/load.py --bundle`. | Accepts each. | +| `fixtures/invalid/` | Invalid packages, each with `expect.json` naming the rule it breaks. | Refuses each, and SHOULD name that rule. | +| `fixtures/keys/` | The test keys that signed the fixtures and the team secret of the checks-only export. | Never uses them for anything else. | + +All fixture text is synthetic and dedicated to the public domain; license fields inside fixtures describe the fictional works. +Each part's CI runs this suite against its own implementation, so the parts cannot drift apart silently. + +## 22.2 Validating a package + +A validator checks, in order, and reports each failure as `path:line: rule: message`: + +1. The manifest: present, valid, sorted, every listed file present with its hash and size, nothing unlisted, paths safe and no symbolic links, required files present. +2. Every file in canonical form, byte for byte, and every record against its schema. +3. The tree ([3](03-nodes.md)), runs and references between nodes, the counts, and the keys ([2.4](02-model.md#24-work-and-document-keys)). +4. The policy and hashing scheme ([12.5](12-package.md#125-text-policies)). +5. The five values of every node, the root and `meta_hash`, when the text is present and the key, if any, is known. +6. The ID table, the corrections and the history root, the witnesses, pages, locations and references, and every file's order. +7. Receipts: IDs, roots, documents, node order, signatures against the package's roster, spot-check keys, seeds and samples, and the fidelity distribution. + +## 22.3 Schemas + +Schemas use draft 2020-12, restricted to the keywords `$schema`, `$id`, `$ref`, `$defs`, `$comment`, `title`, `description`, `examples`, `default`, `deprecated`, `type`, `enum`, `const`, `properties`, `required`, `additionalProperties`, `patternProperties`, `propertyNames`, `minProperties`, `maxProperties`, `dependentRequired`, `items`, `prefixItems`, `minItems`, `maxItems`, `uniqueItems`, `contains`, `minLength`, `maxLength`, `pattern`, `format`, `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `oneOf`, `anyOf`, `allOf`, `not`, `if`, `then` and `else`. +Patterns avoid `\d`, `\w`, `\s`, `\b` and lookbehind, whose meaning differs between regular-expression dialects. +A schema checks shape; the chapters' rules, such as the five values, are checked by validators. + +## 22.4 Rules + +[registry/rules.json](../registry/rules.json) lists every rule ID with its meaning. +Rule IDs are stable: a rule's meaning never changes, and a retired rule's ID is never reused. + +| Prefix | Covers | +| --- | --- | +| `package.` | The manifest, paths, files and schemas. | +| `doc.tree.`, `doc.node.`, `doc.run.`, `doc.table.` | The tree, node content and runs. | +| `doc.hash.` | The five values, the root and the metadata hash. | +| `doc.id.`, `doc.order.` | The ID table and file order. | +| `doc.policy.` | Text policies and keyed hashing. | +| `doc.key.`, `doc.counts`, `doc.history` | The keys, the counts and the history root of `document.json`. | +| `doc.correction.`, `correction.` | A package's corrections, and the gate. | +| `doc.receipt.`, `doc.qa.`, `doc.fidelity.` | Receipts, spot-checks and levels. | +| `doc.witness.`, `doc.page.`, `doc.location.`, `doc.reference.` | Witnesses and geometry. | +| `grade.` | Grading. | + +## 22.5 Stability + +Within a major version of a format, a valid file stays valid, and every value the chapters define is computed the same way. +Rule IDs, enumeration values and format identifiers are never reused with another meaning. +A `candidate` format changes only with a recorded reason and a new or changed vector; a `provisional` one may change more freely, and says so in [registry/formats.json](../registry/formats.json). diff --git a/spec/23-log.md b/spec/23-log.md new file mode 100644 index 0000000..2b5d288 --- /dev/null +++ b/spec/23-log.md @@ -0,0 +1,68 @@ +# 23. The transparency log + +A receipt's `at` is what its signer wrote, and a roster is a file a package carries. +Neither proves that a receipt existed before the key that signed it was revoked, or that the roster a verifier holds is the one the team published. +A team's transparency log settles both: an append-only record of every receipt, revocation and roster the team publishes, whose state is a Merkle tree root that the team signs and that witnesses may cosign. +The log is the same tree as receipts and the correction history ([8.5](08-fidelity.md#85-merkle-roots), [11.5](11-corrections.md#115-the-history-root)), with the same proofs. +Both formats of this chapter are `provisional` ([0.4](00-introduction.md#04-status)): the design follows the specifications that transparency logs share, and the first deployment will shape the details. + +## 23.1 Entries + +An entry, `scienting-log-entry/1`, is one item of the tree, `[kind, id, hash]`: + +| `kind` | `id` | `hash` | +| --- | --- | --- | +| `receipt` | The receipt's record ID. | Its record hash ([8.4](08-fidelity.md#84-record-hashes-and-signatures)). | +| `revocation` | The revocation's record ID. | Its record hash. | +| `roster` | The store the roster is for. | SHA-256 of the canonical JSON of the roster. | + +Entries are appended in the order the team publishes them and never removed. +The leaf hash of an entry is SHA-256 of the byte 0x00 and its canonical JSON, the interior hashes follow RFC 9162, and the root over no entries is SHA-256 of the empty string, as for the history root. +A roster is logged before any receipt a key it adds may sign, so a verifier can find the roster that governed a receipt by looking at the entries before it. + +## 23.2 Checkpoints + +A checkpoint, `scienting-checkpoint/1`, is a signed note in the format transparency logs share: an origin line, the tree size, the root hash in Base64, an empty line, and one signature line per signer. + +```text +scient.ing/log/smithlab +41 +Q2xlYXIgdGV4dCBpcyBub3QgYSByb290IGhhc2guLi4uLi4uLi4= + +— ana AAAAAAHZ… +``` + +The origin names the log, and a team's logs are named `scient.ing/log/<store>` or under a domain the team controls. +A signature line is an em dash (U+2014), a space, the signer's roster key, a space, and Base64 of the signer's four-byte key hash followed by the signature. +The key hash is the first four bytes of SHA-256 of the signer's name, a newline, the byte 0x01 and the Ed25519 public key; the signature is Ed25519 over the note's first three lines, each ending in a newline. +A note parsed into JSON has `format`, `origin`, `size`, `root` as hex, `signatures` as `{name, key_hash, value}` and the `note` text itself; the schema is `checkpoint.schema.json`. +`checkpoint.jsonl` gives a checkpoint over the example paper's receipts and its verification. + +A checkpoint may carry further signature lines from witnesses: roster keys with the `witness` purpose, held by independent parties, that cosign only a checkpoint consistent with every earlier one they saw. +A verifier that holds two checkpoints of one log checks a consistency proof between them ([11.5](11-corrections.md#115-the-history-root)); a log that cannot produce one has rewritten its past. +A project accepts a checkpoint when its origin is the project's log, a key with the role `owner` and the `sign` purpose signed it, and at least the project's `threshold` of its listed witnesses cosigned it ([20](20-projects.md)); `fixtures/records/log/checkpoint` is signed by the team and one witness. + +## 23.3 What a log settles + +When a project names a log in its settings ([20](20-projects.md)), a receipt counts toward a level only when the log holds it, and the log's order replaces the records' own times in two rules: + +1. A revocation of a signer's period revokes the receipts logged before the revocation that fall in the period; a receipt logged after a revocation of its key never counts, whatever its `at` says. +2. The roster that governs a receipt is the latest roster entry before it. + +A reader fetches the latest checkpoint, verifies its signatures against the roster and its consistency with the checkpoint it last saw, then verifies inclusion proofs for the receipts it relies on. +Without a log the rules of [8.6](08-fidelity.md#86-receipt-status) stand, and the `at` of each record is taken at its word. + +## 23.4 Serving a log + +A log is served as static files in the tile layout transparency logs share, so that a client fetches only the subtrees it needs and any file server can host a log. + +| Path | Holds | +| --- | --- | +| `checkpoint` | The latest checkpoint note ([23.2](#232-checkpoints)). | +| `tile/<L>/<N>` | Hash tile N of level L: the 32-byte hashes of the 256 complete subtrees of 256^L entries each that the tile covers, in order. Level 0 holds the leaf hashes. | +| `tile/<L>/<N>.p/<W>` | The rightmost, partial tile of level L, holding W hashes. | +| `tile/entries/<N>` and `tile/entries/<N>.p/<W>` | The entries themselves, 256 to a tile, as canonical JSON Lines. | + +N is written as 3-digit groups, every group but the last prefixed `x`: tile 1234067 is `tile/0/x001/x234/067`. +A tile at level L holds only the hashes of complete subtrees, so the hashes a partial tree still needs are computed from lower levels, as RFC 9162 computes a root from its subtrees. +`fixtures/records/log/` is the example paper's log in this layout, and `checkpoint.jsonl` lists its tile paths. diff --git a/spec/README.md b/spec/README.md new file mode 100644 index 0000000..d8ed0cd --- /dev/null +++ b/spec/README.md @@ -0,0 +1,52 @@ +# The paperspec specification + +This specification states exactly what each paperspec file holds and how every value in it is computed. +The schemas, SQL, JSON-LD context, registries, vectors and fixtures are normative too, and each chapter says which of them it relies on. +A chapter and a vector that disagree signal a bug, so please report it in the repository, <https://git.scient.ing/infra/paperspec>. + +Two readers will get the most from it: implementers who build a reader, writer, converter or checker, and experts who want the precise rules. +Newcomers should start with the [guides](../docs/README.md), which explain what the formats are for. +This text assumes you know why and tells you how. + +## Reading paths + +Find the row for the job you are doing and read its chapters after those in the first row. +Chapter numbers are those in the table below. + +| If you are writing | Read | +| --- | --- | +| Anything at all | 0, 1, 3, 4 and 5: introduction, conventions, nodes, identity and the content values. | +| A reader of packages | Then 2, 6, 7 and 12: the model, anchors, geometry and the package. | +| A converter | Then 9, 10 and 11: figures and tables, references, and corrections with the gate. | +| A store or a server | Then 8, 13, 14 and 23: receipts, the database form, rights, and the transparency log. | +| A writer or reader of annotation, teaching or data files | Then 15 to 21. | +| A validator | Chapter 22, with [registry/rules.json](../registry/rules.json). | + +## Chapters + +| Chapter | Subject | +| --- | --- | +| [0. Introduction](00-introduction.md) | Scope, conformance, versions and status, and how the repository is arranged | +| [1. Shared conventions](01-conventions.md) | Canonical JSON, numbers, hashes, normalization, offsets, times, determinism, IDs, keys, files and prose | +| [2. Works, versions, witnesses and documents](02-model.md) | The four objects; `document.json` and `witnesses.json` | +| [3. Nodes](03-nodes.md) | Nodes, their kinds and children, content, attributes, inline runs and the plain projection | +| [4. Identity](04-identity.md) | Minting IDs, permanence, retirement, aliases, `ids.jsonl`, store-qualified names and record IDs | +| [5. Content values](05-hashes.md) | The five content values, the projections, alignment, suspects, keyed hashes and the metadata hash | +| [6. Addresses and anchors](06-anchors.md) | Addresses, anchors and the five resolutions, with drift | +| [7. Geometry](07-geometry.md) | Page fingerprints, stamp rules, `pages.jsonl` and `locations.jsonl` | +| [8. Fidelity, receipts and spot-checks](08-fidelity.md) | Fidelity levels, receipts, signatures, Merkle roots, the roster, revocations, spot-checks and error bounds | +| [9. Figures, tables and equations](09-figures-tables-equations.md) | Figures, panels, tables, cells and equations | +| [10. References and citations](10-references.md) | Reference nodes, `references.jsonl` and its resolutions, and sentence-level citations | +| [11. Corrections](11-corrections.md) | Corrections and the gate | +| [12. The package](12-package.md) | The files of a package, paths, manifest, provenance, text policies and assets | +| [13. The database form and the bundle](13-database.md) | The database form and the SQLite bundle | +| [14. Rights](14-rights.md) | Rights records, policies, stages and backends | +| [15. Datasets](15-datasets.md) | Frictionless Data Packages with units, uncertainty and origin; `anchors.jsonl`; content hash | +| [16. Digitization records](16-digitization.md) | How values were read off a figure panel: target, axes, series, method, verification and confirmation | +| [17. Views](17-views.md) | Vega-Lite specifications that pin their data, and optional computations | +| [18. Layers and annotations](18-layers.md) | Layers and annotations | +| [19. Exercises, submissions and grades](19-exercises.md) | Exercises, submissions and grades | +| [20. Projects](20-projects.md) | Members and roles, documents, reading paths, held layers, datasets, views and drafts, and settings | +| [21. Drafts](21-drafts.md) | Drafts: snapshots and sentence-ID sidecars | +| [22. Conformance](22-conformance.md) | Conformance, the suite and the rule catalog | +| [23. The transparency log](23-log.md) | A team's log of receipts, revocations and rosters, its checkpoints, and what it settles | diff --git a/sql/README.md b/sql/README.md new file mode 100644 index 0000000..5f1151a --- /dev/null +++ b/sql/README.md @@ -0,0 +1,66 @@ +# SQL + +This folder holds the table definitions for the database form of packages, a team's store, and the bundle. + +## What the database form is for + +A package is a folder of canonical JSON files, one document per folder ([chapter 12](../spec/12-package.md)). +Canonical JSON is JSON with exactly one valid byte sequence, so a file's hash changes only when its content does. + +Handing over a folder is easy. +Querying across hundreds of documents in folders is hard. +The database form holds the same data as rows so that a team can ask SQL questions of it, and a package loaded into the tables unloads back to the same bytes. +About 500 documents come to about a million and a half rows, and SQLite and Dolt hold that comfortably ([chapter 13](../spec/13-database.md#132-tables)). + +## The three files + +| File | Holds | Runs on | +| --- | --- | --- | +| `doc.sql` | Documents: works, documents, witnesses, nodes, pages, locations, references, citations, corrections, IDs, receipts, revocations, suspects and package files. | SQLite, Dolt, PostgreSQL | +| `store.sql` | What a team adds: roster keys, projects, members, reading paths, layers, annotations, datasets, digitizations, views, policies, submissions and grades. Load `doc.sql` first. | SQLite, Dolt, PostgreSQL | +| `bundle-sqlite.sql` | The bundle's extra tables: metadata, a full-text index (FTS5, SQLite's search extension) and room for embeddings. Load both files above first. | SQLite | + +## Creating a database + +```sh +sqlite3 lab.db < sql/doc.sql && sqlite3 lab.db < sql/store.sql +psql -d lab -f sql/doc.sql && psql -d lab -f sql/store.sql +dolt sql < sql/doc.sql && dolt sql < sql/store.sql +``` + +The PostgreSQL database `lab` and the Dolt repository must already exist. +The `sqlite3` line runs as shown; the `psql` and `dolt` lines follow the portability rules of [chapter 13](../spec/13-database.md#131-portability) but have not been run on those engines in this repository. + +To load packages into SQLite without pixi, run `python3 tools/load.py --sqlite lab.db PACKAGE…` with Python 3.14 and two packages, `jsonschema` and `cryptography` installed. +The file [docs/examples.md](../docs/examples.md#load-packages-into-sqlite) has queries to try. +The loader copies files that have no table (assets, dataset files, derived files) by SHA-256 into `lab.db.assets/`. + +## A first query + +The query below finds every sentence that cites a given reference, which is the citation's context. +It returns sentence IDs, and `nodes.content` holds each sentence's text. + +```sql +SELECT c.sentence +FROM citations c +JOIN refs r ON r.doc_key = c.doc_key AND r.node = c.ref_node +WHERE c.doc_key = 'hale2026harmonic-damb' AND r.label = '2'; +``` + +On `fixtures/packages/hale2026harmonic-damb` it returns one row, `hca6dc5`: the sentence ending "served as the first test case, with a bending band near 1595 cm⁻¹." + +## Conventions + +- Foreign keys: none. + Validators check references, so the same file runs everywhere. +- Types: enumerations are `VARCHAR` with a `CHECK`, JSON values are canonical JSON in `TEXT`, and booleans are `INTEGER` 0 or 1. +- Names: no table, column or index name is reserved in SQLite, PostgreSQL or MySQL (Dolt is MySQL-compatible). + The formats' `key`, `index`, `at`, `by`, `before` and `after` become `doc_key`, `idx`, `made_at`, `signer`, `before_hash` and `after_hash`. +- Round trip: each row keeps every property of its record, so unloading restores the same bytes and the same manifest hash. + Unloading copies the files with no table from the asset store, which must travel with the database. `tools/check.py` tests this for every fixture package. +- Derived tables: `citations`, `receipt_nodes` and `annotation_targets` are built on load for queries and are not part of the package. + +## Status + +The version is 0.1.0. +In `registry/formats.json`, `scienting-doc/1` is `candidate`, and the bundle and the project, dataset, digitization and view formats are `provisional`. [Chapter 13](../spec/13-database.md) defines the mapping from files to tables. diff --git a/sql/bundle-sqlite.sql b/sql/bundle-sqlite.sql new file mode 100644 index 0000000..4f0f67b --- /dev/null +++ b/sql/bundle-sqlite.sql @@ -0,0 +1,32 @@ +-- scienting-bundle/1: the SQLite file a reader or a server reads. +-- Normative: spec/13-database.md. SQLite only: it uses FTS5. +-- A bundle holds sql/doc.sql and sql/store.sql, then these tables. +-- License: CC0-1.0. + +CREATE TABLE bundle_meta ( + name VARCHAR(64) NOT NULL, + value TEXT NOT NULL, + PRIMARY KEY (name) +); + +-- One row per searchable unit: a sentence, a cell, an equation outside a sentence, or a figure-text item. +-- `unit` is sentence, cell, equation or figure-text. `context` is the kind of the node's parent: +-- paragraph, heading, caption, footnote, row and so on. A figure-text item names its panel as `node` +-- and its role as `context`. `text` is the normalized plain projection; withheld text is never indexed. +CREATE VIRTUAL TABLE search USING fts5( + doc_key UNINDEXED, + node UNINDEXED, + unit UNINDEXED, + context UNINDEXED, + text, + tokenize = 'unicode61 remove_diacritics 2' +); + +-- Reserved for embeddings with sqlite-vec; see spec/13-database.md. +CREATE TABLE embeddings_meta ( + model VARCHAR(128) NOT NULL, + dimensions INTEGER NOT NULL, + rights_use VARCHAR(64) NOT NULL, + made_at VARCHAR(20) NOT NULL, + PRIMARY KEY (model) +); diff --git a/sql/doc.sql b/sql/doc.sql new file mode 100644 index 0000000..355876d --- /dev/null +++ b/sql/doc.sql @@ -0,0 +1,219 @@ +-- scienting-doc/1: the database form of packages. +-- Normative: spec/13-database.md. +-- Portable to SQLite 3.37+, Dolt and PostgreSQL 12+: +-- no foreign keys, enumerations as VARCHAR with CHECK, JSON as canonical JSON text, +-- booleans as INTEGER 0 or 1, and no column name reserved in any of the three. +-- License: CC0-1.0. + +CREATE TABLE works ( + work_key VARCHAR(128) NOT NULL, + same_as TEXT NOT NULL, + PRIMARY KEY (work_key) +); + +CREATE TABLE documents ( + doc_key VARCHAR(128) NOT NULL, + store VARCHAR(128), + aliases TEXT, + kind VARCHAR(32) NOT NULL CHECK (kind IN ('article', 'supplement', 'chapter', 'book', 'thesis', 'report', 'draft', 'course-material', 'other')), + work TEXT NOT NULL, + version TEXT NOT NULL, + relations TEXT NOT NULL, + meta TEXT NOT NULL, + language VARCHAR(35) NOT NULL, + license TEXT, + policy VARCHAR(16) NOT NULL CHECK (policy IN ('full', 'checks-only')), + hashing TEXT NOT NULL, + root_hash VARCHAR(64) NOT NULL, + meta_hash VARCHAR(64) NOT NULL, + history VARCHAR(64) NOT NULL, + rev INTEGER NOT NULL CHECK (rev >= 0), + counts TEXT NOT NULL, + fidelity TEXT NOT NULL, + provenance TEXT NOT NULL, + roster TEXT, + package_hash VARCHAR(64) NOT NULL, + PRIMARY KEY (doc_key) +); + +CREATE TABLE witnesses ( + doc_key VARCHAR(128) NOT NULL, + id VARCHAR(32) NOT NULL, + ord INTEGER NOT NULL, + sha256 VARCHAR(64) NOT NULL, + size BIGINT NOT NULL, + kind VARCHAR(16) NOT NULL CHECK (kind IN ('pdf', 'jats', 'latex', 'html', 'epub', 'typst', 'xml', 'image', 'other')), + media_type VARCHAR(128) NOT NULL, + pages INTEGER, + text_layer INTEGER CHECK (text_layer IN (0, 1)), + version_label VARCHAR(128), + origin TEXT NOT NULL, + rights TEXT NOT NULL, + PRIMARY KEY (doc_key, id) +); +CREATE INDEX witnesses_sha256 ON witnesses (sha256); + +CREATE TABLE nodes ( + doc_key VARCHAR(128) NOT NULL, + id VARCHAR(16) NOT NULL, + seq INTEGER NOT NULL, + kind VARCHAR(24) NOT NULL CHECK (kind IN ( + 'document', 'front', 'title', 'authors', 'abstract', 'keywords', 'notes', 'section', 'heading', + 'paragraph', 'sentence', 'equation', 'equation-line', 'figure', 'panel', 'caption', 'figure-note', + 'table', 'table-head', 'table-body', 'table-note', 'row', 'cell', 'list', 'item', 'quote', 'code', + 'algorithm', 'theorem', 'footnote', 'back', 'acknowledgments', 'references', 'reference', 'appendix')), + parent VARCHAR(16), + ord INTEGER NOT NULL CHECK (ord >= 0), + label VARCHAR(256), + attrs TEXT, + content TEXT, + withheld INTEGER CHECK (withheld IN (0, 1)), + fidelity VARCHAR(2) CHECK (fidelity IN ('F0', 'F1', 'F2', 'F3')), + prov TEXT, + text_hash VARCHAR(64) NOT NULL, + match_hash VARCHAR(64) NOT NULL, + align_key VARCHAR(64) NOT NULL, + own_hash VARCHAR(64) NOT NULL, + node_hash VARCHAR(64) NOT NULL, + PRIMARY KEY (doc_key, id) +); +CREATE INDEX nodes_parent ON nodes (doc_key, parent, ord); +CREATE INDEX nodes_seq ON nodes (doc_key, seq); +CREATE INDEX nodes_match_hash ON nodes (match_hash); + +CREATE TABLE pages ( + doc_key VARCHAR(128) NOT NULL, + witness VARCHAR(32) NOT NULL, + page INTEGER NOT NULL CHECK (page >= 1), + page_fp VARCHAR(64) NOT NULL, + size TEXT NOT NULL, + page_label VARCHAR(64), + text_layer INTEGER NOT NULL CHECK (text_layer IN (0, 1)), + stamps_removed TEXT, + PRIMARY KEY (doc_key, witness, page) +); +CREATE INDEX pages_page_fp ON pages (page_fp); + +CREATE TABLE locations ( + doc_key VARCHAR(128) NOT NULL, + node VARCHAR(16) NOT NULL, + page_fp VARCHAR(64) NOT NULL, + page INTEGER NOT NULL CHECK (page >= 1), + page_label VARCHAR(64), + boxes TEXT NOT NULL, + approx INTEGER CHECK (approx IN (0, 1)), + PRIMARY KEY (doc_key, node, page, page_fp) +); + +CREATE TABLE refs ( + doc_key VARCHAR(128) NOT NULL, + node VARCHAR(16) NOT NULL, + label VARCHAR(64), + csl TEXT, + resolution TEXT NOT NULL, + PRIMARY KEY (doc_key, node) +); + +-- Derived on load from cite runs; not part of the package. +CREATE TABLE citations ( + doc_key VARCHAR(128) NOT NULL, + sentence VARCHAR(16) NOT NULL, + ref_node VARCHAR(16) NOT NULL, + ord INTEGER NOT NULL, + PRIMARY KEY (doc_key, sentence, ord, ref_node) +); +CREATE INDEX citations_ref ON citations (doc_key, ref_node); + +CREATE TABLE corrections ( + doc_key VARCHAR(128) NOT NULL, + idx INTEGER NOT NULL CHECK (idx >= 1), + id VARCHAR(32) NOT NULL, + op VARCHAR(16) NOT NULL CHECK (op IN ('replace', 'insert', 'delete', 'split', 'merge', 'move', 'reclassify', 'relabel', 'set')), + target VARCHAR(16), + evidence TEXT NOT NULL, + author TEXT NOT NULL, + reason TEXT NOT NULL, + made_at VARCHAR(20) NOT NULL, + before_hash VARCHAR(64), + after_hash VARCHAR(64), + path TEXT, + touched TEXT NOT NULL, + details TEXT NOT NULL, + PRIMARY KEY (doc_key, idx) +); +CREATE INDEX corrections_target ON corrections (doc_key, target); + +CREATE TABLE node_ids ( + doc_key VARCHAR(128) NOT NULL, + id VARCHAR(128) NOT NULL, + kind VARCHAR(8) NOT NULL CHECK (kind IN ('retired', 'alias')), + successor VARCHAR(16), + node_kind VARCHAR(24), + rev INTEGER, + PRIMARY KEY (doc_key, id) +); + +CREATE TABLE receipts ( + doc_key VARCHAR(128) NOT NULL, + id VARCHAR(32) NOT NULL, + level VARCHAR(2) NOT NULL CHECK (level IN ('F1', 'F2', 'F3')), + scope VARCHAR(64) NOT NULL, + rev INTEGER NOT NULL, + root VARCHAR(64) NOT NULL, + nodes TEXT NOT NULL, + records TEXT, + evidence TEXT NOT NULL, + signer VARCHAR(128) NOT NULL, + made_at VARCHAR(20) NOT NULL, + qa TEXT, + export_of VARCHAR(32), + keyed TEXT, + signature TEXT NOT NULL, + PRIMARY KEY (doc_key, id) +); +CREATE INDEX receipts_doc ON receipts (doc_key, made_at); + +-- Derived on load from receipts.nodes. +CREATE TABLE receipt_nodes ( + receipt VARCHAR(32) NOT NULL, + doc_key VARCHAR(128) NOT NULL, + node VARCHAR(16) NOT NULL, + node_hash VARCHAR(64) NOT NULL, + PRIMARY KEY (doc_key, receipt, node) +); +CREATE INDEX receipt_nodes_node ON receipt_nodes (doc_key, node); + +CREATE TABLE revocations ( + doc_key VARCHAR(128) NOT NULL, + id VARCHAR(32) NOT NULL, + receipt VARCHAR(32), + revoked_signer VARCHAR(128), + period_from VARCHAR(20), + period_to VARCHAR(20), + reason TEXT NOT NULL, + signer VARCHAR(128) NOT NULL, + made_at VARCHAR(20) NOT NULL, + signature TEXT NOT NULL, + -- A revocation of a signer's period carries no document, so two packages may carry the same record. + PRIMARY KEY (doc_key, id) +); + +CREATE TABLE suspects ( + doc_key VARCHAR(128) NOT NULL, + id VARCHAR(32) NOT NULL, + kind VARCHAR(16) NOT NULL CHECK (kind IN ('word', 'number', 'equation', 'structure', 'join', 'added', 'dropped', 'boundary', 'reading')), + node VARCHAR(16), + record TEXT NOT NULL, + PRIMARY KEY (doc_key, id) +); + +-- Files a package holds that have no table of their own: assets, datasets and derived files. +-- Their bytes live in the asset store, by SHA-256. +CREATE TABLE package_files ( + doc_key VARCHAR(128) NOT NULL, + path VARCHAR(512) NOT NULL, + sha256 VARCHAR(64) NOT NULL, + size BIGINT NOT NULL, + present INTEGER NOT NULL CHECK (present IN (0, 1)), + PRIMARY KEY (doc_key, path) +); diff --git a/sql/store.sql b/sql/store.sql new file mode 100644 index 0000000..c65b793 --- /dev/null +++ b/sql/store.sql @@ -0,0 +1,155 @@ +-- The team store: everything a team adds to its documents. +-- Normative: spec/13-database.md. Load sql/doc.sql first. +-- Portable to SQLite 3.37+, Dolt and PostgreSQL 12+, under the same rules as sql/doc.sql. +-- License: CC0-1.0. + +CREATE TABLE roster_keys ( + store VARCHAR(128) NOT NULL, + id VARCHAR(128) NOT NULL, + person TEXT NOT NULL, + role VARCHAR(16) NOT NULL CHECK (role IN ('owner', 'editor', 'reader', 'guest')), + scheme VARCHAR(16) NOT NULL CHECK (scheme IN ('ed25519', 'ssh', 'gpg', 'sigstore', 'cose', 'ml-dsa-65')), + public_key TEXT NOT NULL, + did VARCHAR(128), + purposes TEXT NOT NULL, + registered_at VARCHAR(20) NOT NULL, + revoked_at VARCHAR(20), + PRIMARY KEY (store, id) +); + +CREATE TABLE projects ( + project_key VARCHAR(128) NOT NULL, + store VARCHAR(128), + name TEXT NOT NULL, + description TEXT, + claims TEXT, + settings TEXT, + record TEXT NOT NULL, + PRIMARY KEY (project_key) +); + +CREATE TABLE members ( + project_key VARCHAR(128) NOT NULL, + person VARCHAR(256) NOT NULL, + role VARCHAR(8) NOT NULL CHECK (role IN ('owner', 'editor', 'reader', 'guest')), + signing_keys TEXT NOT NULL, + PRIMARY KEY (project_key, person) +); + +CREATE TABLE project_documents ( + project_key VARCHAR(128) NOT NULL, + doc_key VARCHAR(257) NOT NULL, + reason TEXT NOT NULL, + tags TEXT, + reading_status TEXT, + PRIMARY KEY (project_key, doc_key) +); + +CREATE TABLE reading_paths ( + project_key VARCHAR(128) NOT NULL, + id VARCHAR(128) NOT NULL, + title TEXT NOT NULL, + steps TEXT NOT NULL, + PRIMARY KEY (project_key, id) +); + +CREATE TABLE layers ( + id VARCHAR(256) NOT NULL, + project_key VARCHAR(128), + label TEXT NOT NULL, + purpose TEXT NOT NULL, + audience VARCHAR(8) CHECK (audience IN ('novice', 'student', 'expert', 'mixed')), + visibility VARCHAR(8) NOT NULL CHECK (visibility IN ('private', 'team', 'public')), + license TEXT NOT NULL, + record TEXT NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE annotations ( + id VARCHAR(256) NOT NULL, + layer VARCHAR(256) NOT NULL, + body_kind VARCHAR(24) NOT NULL CHECK (body_kind IN ('gloss', 'claim-link', 'symbol', 'comment', 'caveat', 'question', 'exercise', 'citation-context', 'prerequisite', 'crosslink', 'translation', 'description', 'generated')), + status VARCHAR(10) NOT NULL CHECK (status IN ('proposed', 'confirmed', 'rejected', 'withdrawn')), + receipt VARCHAR(32), + creator VARCHAR(256) NOT NULL, + created VARCHAR(20) NOT NULL, + record TEXT NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX annotations_layer ON annotations (layer); + +-- Derived from annotation targets, so a reader finds the annotations on a node. +CREATE TABLE annotation_targets ( + annotation VARCHAR(256) NOT NULL, + ord INTEGER NOT NULL, + doc_key VARCHAR(257), + node VARCHAR(128), + target_annotation VARCHAR(256), + PRIMARY KEY (annotation, ord) +); +CREATE INDEX annotation_targets_node ON annotation_targets (doc_key, node); + +CREATE TABLE datasets ( + id VARCHAR(128) NOT NULL, + doc_key VARCHAR(257), + content_hash VARCHAR(64) NOT NULL, + descriptor TEXT NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE dataset_values ( + dataset VARCHAR(128) NOT NULL, + resource VARCHAR(128) NOT NULL, + row_key VARCHAR(128) NOT NULL, + field VARCHAR(128) NOT NULL, + printed VARCHAR(64), + origin_kind VARCHAR(10) NOT NULL CHECK (origin_kind IN ('reported', 'digitized', 'computed', 'measured')), + anchor TEXT, + PRIMARY KEY (dataset, resource, row_key, field) +); + +CREATE TABLE digitizations ( + id VARCHAR(32) NOT NULL, + doc_key VARCHAR(257) NOT NULL, + panel VARCHAR(16) NOT NULL, + page_fp VARCHAR(64), + method VARCHAR(8) NOT NULL CHECK (method IN ('manual', 'traced', 'proposed')), + confirmation VARCHAR(32), + dataset VARCHAR(128), + record TEXT NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE views ( + id VARCHAR(128) NOT NULL, + project_key VARCHAR(128), + spec TEXT NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE policies ( + id VARCHAR(32) NOT NULL, + project_key VARCHAR(128), + signer VARCHAR(128) NOT NULL, + made_at VARCHAR(20) NOT NULL, + valid_until VARCHAR(20), + record TEXT NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE submissions ( + id VARCHAR(32) NOT NULL, + exercise VARCHAR(256) NOT NULL, + student VARCHAR(64) NOT NULL, + submitted_at VARCHAR(20) NOT NULL, + record TEXT NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE grades ( + submission VARCHAR(32) NOT NULL, + score VARCHAR(32) NOT NULL, + max_score VARCHAR(32) NOT NULL, + record TEXT NOT NULL, + PRIMARY KEY (submission) +); diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..7a3a7dc --- /dev/null +++ b/tools/README.md @@ -0,0 +1,71 @@ +# Tools + +This page is for anyone who wants to run the repository's checks, rebuild its examples or load a document into a database. +Newcomers get each term defined where it first appears. +Implementers get the commands and the traps. + +These programs are the repository's reference implementation. +They apply every rule of the specification, so the rest of the repository can be checked against them. +Two build and check the repository, one validates packages and proposed corrections, and one loads packages into SQLite, a database stored in a single file. +They need Python 3.14 and two packages, `jsonschema` and `cryptography`, and are licensed Apache-2.0. + +A package is the folder of files that holds one document, such as `fixtures/packages/hale2026harmonic`. +A vector is a test case: an input and the exact output every implementation must compute (see [the vectors](../vectors/README.md)). +A fixture is an example file or package under `fixtures/`. + +| Program | Does | +| --- | --- | +| `check.py` | Checks everything: schemas, records, packages and the zipped package, the broken packages, every vector, a byte-for-byte rebuild, the SQL (a database query language) round trip, the counts the prose states, and the prose. `--quick` skips the rebuild. | +| `build.py` | Builds `fixtures/` and `vectors/` from the hand-written sources in `fixtures/src/` and the cases it defines. `--out DIR` builds into another folder. | +| `validate.py` | Validates packages, as folders or as zipped packages (`.sct.zip`, unpacked under the rules of [spec/12 §12.2](../spec/12-package.md#122-paths)): `python3 tools/validate.py PACKAGE [PACKAGE ...]`. With `--correction PROPOSALS` it runs proposed corrections through the gate against one package's current state, and prints the record each would append or the rule it breaks, without writing anything ([spec/11 §11.4](../spec/11-corrections.md#114-the-gate)). | +| `load.py` | Validates packages, folders or zipped, then loads them into a SQLite database with the tables of `sql/`: `python3 tools/load.py --sqlite lab.db PACKAGE [PACKAGE ...]`. With `--bundle --built-from REV` it builds a new bundle instead, with the full-text search index ([spec/13 §13.5](../spec/13-database.md#135-the-bundle)). | +| `site.py` | Builds the website into `_site/`: every file of the repository at its own path, and each Markdown file rendered as a page beside it, with a vocabulary page, folder listings and a search index. It uses only the standard library. `pixi run check` builds it into a temporary folder and checks every link ([deploy/](../deploy/README.md)). | +| `stress.py` | Stresses the oracle with random inputs from a seeded generator: `python3 tools/stress.py [--seed N] [--rounds N]`. It checks the invariants the chapters state rather than the vectors' values, such as canonical JSON round trips, corrections keeping the five values consistent with a full recomputation, anchors always resolving to one of the five outcomes, the zip reader never writing outside its folder, and a mutated package always being refused. | +| `oracle/` | A compact implementation of every rule. `build.py` uses it to compute expected values, and `check.py` uses it to recompute them. | + +## When to run what + +Each program is also a pixi task. +Pixi sets up a pinned Python and the other packages the repository uses. +The commands `pixi run check`, `pixi run quick`, `pixi run build` and `pixi run load` then work from anywhere in the repository. +`pixi run check` lints the Markdown first. + +Run the programs directly from the repository root if you do not use pixi: + +```sh +python3 tools/check.py # everything +python3 tools/check.py --quick # everything except the rebuild +python3 tools/build.py --out /tmp/rebuilt +python3 tools/validate.py fixtures/packages/hale2026harmonic +python3 tools/load.py --sqlite lab.db fixtures/packages/hale2026harmonic +``` + +A passing check ends with `All checks pass.` +The load command prints `hale2026harmonic: 75 nodes`, one line per package, and writes `lab.db` with a folder `lab.db.assets/` beside it for files that have no table of their own. +It validates every package first and loads nothing if one fails, printing each failure as `package: where: rule: message`. +The full and checks-only forms of one document share its key, so they go into separate databases. +Each program prints its options with `--help` and refuses options it does not know. +`build.py` rebuilds `fixtures/` and `vectors/` in place unless you pass `--out`. + +Run `pixi run check` before every commit. +Run `pixi run build` after you change a fixture source, a rule in `oracle/` or a case in `build.py`, and commit the regenerated files with the change. +The check rebuilds into a temporary folder and compares every file byte for byte, so it fails on out-of-date files. + +## About the oracle + +An oracle is a reference computation: a slow, plain program whose answers count as the expected ones. +It is not a production reader or writer. +The oracle exists so that no expected value in this repository is typed by hand. + +It favors clarity, and leaves the cryptography and schema validation to established packages. +Ed25519 (a digital signature scheme) and HKDF come from `cryptography`, and JSON Schema (a format that describes the shape of JSON data) validation from `jsonschema`. +The VRF of RFC 9381 (`oracle/vrf.py`) and ML-DSA-65 of FIPS 204 (`oracle/mldsa.py`) are written out in plain Python, slow and clear, and checked against the standards' own test vectors. +The oracle still refuses any schema that uses a keyword outside the subset the schemas are restricted to. +Canonical JSON goes through Python's built-in JSON encoder, and falls back to an exact RFC 8785 serializer for the values that encoder writes differently: floating-point numbers, integers beyond 2^53 and some non-ASCII member names. + +Hashes are kept incrementally. +A node's five values depend only on its own subtree, so after a correction the oracle rehashes only the nodes that changed and their ancestors, and a container's projections are its children's cached projections joined. +`check.py` compares the result after every correction with a slow computation that projects each node from its whole subtree. + +Do not build on it as a library. +Implementations follow the [specification](../spec/README.md) and test themselves against the [vectors](../vectors/README.md). diff --git a/tools/__init__.py b/tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tools/build.py b/tools/build.py new file mode 100644 index 0000000..93e33ef --- /dev/null +++ b/tools/build.py @@ -0,0 +1,1869 @@ +#!/usr/bin/env python3 +"""Build every fixture and test vector from fixtures/src and the cases below. + +Non-normative tooling. +The build is deterministic: run it twice and the output is byte-identical; `tools/check.py` verifies that. +Usage: python3 tools/build.py [--out DIR] (default: the repository itself) +""" + +import base64 +import copy +import hashlib +import json +import os +import shutil +import struct +import sys +import zipfile +import zlib +from fractions import Fraction + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, ROOT) + +from tools.oracle import align as AL # noqa: E402 +from tools.oracle import anchors as AN # noqa: E402 +from tools.oracle import corrections as CO # noqa: E402 +from tools.oracle import crypto, fingerprint as FP, grade as GR, hashing, jcs, receipts as RC, rights as RI # noqa: E402 +from tools.oracle import keys as K, log as LG, mldsa, targets as TG, vrf # noqa: E402 +from tools.oracle.model import LEAVES, MATH_KINDS, RUN_KINDS, VERBATIM_KINDS, Doc # noqa: E402 +from tools.oracle.notation import fold_math # noqa: E402 +from tools.oracle.package import ZIP_EXTENSION, history_items, jsonl, line, witness_id, write, write_zip # noqa: E402 +from tools.oracle.schema import Store # noqa: E402 +from tools.oracle.text import letter_first, mint_node_id, norm, record_id, sha256_hex # noqa: E402 +from tools.oracle.tree import Refusal, _flatten, mint_ids, validate_structure # noqa: E402 + +VERSION = "0.1.0" +STORE = "smithlab" +SCHEMAS = Store(os.path.join(ROOT, "schemas")) + + +def H(s): + return sha256_hex(s) + + +def secret(name): + return hashlib.sha256(("paperspec fixture key: " + name).encode()).digest() + + +KEYS = { + "ana": {"name": "Ana Example", "role": "owner", "purposes": ["sign"]}, + "ben": {"name": "Ben Example", "role": "editor", "purposes": ["sign"]}, + "ben-spot": {"name": "Ben Example", "role": "editor", "purposes": ["spot-check"]}, + "cara": {"name": "Cara Example", "role": "reader", "purposes": ["sign"]}, + "dana": {"name": "Dana Example", "role": "editor", "purposes": ["sign"], "scheme": "ml-dsa-65"}, + "wit": {"name": "Open Witness (fictional)", "role": "guest", "purposes": ["witness"]}, +} +TEAM_SECRET = hashlib.sha256(b"paperspec fixture team secret: smithlab").digest() +# NIST ACVP ML-DSA-keyGen-FIPS204, parameter set ML-DSA-65, test case 26: the seed and the public key it gives. +NIST_SEED = "a991fd42b071d49c48ae3e75c647459e0daad1e1ba356a04801912d3294bcff8" +NIST_PK = "36db0b5dce98bd190cb139e80b71b49c7d7040b71c5a1f3412c46bde939192b1b57ccb88ac2714c1240cb0eb62c689e031aea3d9f3eb3ed7bfa45931d288dcae3413199b31a7032560dce8a61e195d13a1440615c2f3aa7dd28c5b1b742bfa400052186721f13d3df9dcfaee348b10d66913c7148913e085e1a4a03c659398dadc6a8e0e0c1a7f9f44d30436db90fd65a6ab8f36137338255653baae8da21526a333426dbd9f76cce0f43212643e854d772018b35ce726bcaaa5ab0651baf8c122e13929bb35b6e4963df2595fdc7237cdaa7234bf776b07f353ccdba12ad3e025138e3492d7f8e929db55dc23e23075f66d57a10492e6a10ae7b758acc2291ca18ba1ca07a5b574ab6d8aac18b9524990ad2f110225b7d82f696300a660a166ad35b3c57ecbab77117c79656fa8ae2a19a7defb2afd2af54683d043be0f933b8eae0d591448ed55d00068cd9fe10b067fcfaac53aedb1e9b667e36c4e30231f85c7aa0a474af2fa4776226f4479555e155528d78b98183cbdf7fae4e7301140f163eb71e991d15fad4a0d2f25a5a62fa2e9bcc823cc2927662e40c538213ded9e2df508e911e4924e507a50861fbb050edbbf56d937206f8fbc6f4cead4cd10d06b73aadcd4aa39703a7a2bffae68b7baa47341b699da9f3b167d4d90efee0a07ee3529a3b5e8648b9cb07ee973e1d8dccf1d16e95092c4a0184ccb4902d6086d9f444aca5fa45f43ca91b351e82585989ffcbd6d2c3471d6b8593aa46f29d0dd9b44e8aa4d8f9a0bc886bb7982c56aab11e23bfdbd8bc674732fadacacae25fa416b2d0cc7743827293336507da4b14c1f0aa2e929af975466dadc89a016f33a0cca2d5c08114cf04b02358805a772536432c44dbe9886130d2d3a0ffa0e175875a2207686f5e562b879eb2957573ab706b942468c20cc69bc566d29d9f151f3cfae71cc97ce4a30722d4679fc1c089b5009935931ee60aac5496b0fd5f24e514c0e20fa1dcc7729184a50fc85fad1d2f32f715fbf55666e49f5a19761f2dd1aa5d1a33c7916eb6a794981c0334176abc493ef30d9eaeaad42e705989dcfcdeb578529a700bd14076a348a2062d6483cc63cd7f55136587aac0e531a06eb2de74e61cfcbbce18f2ada5a741f683bf101f71432ee659dd1508e0c8fb2400e0ccbe435da3466d543d3ef5ba369e125c0b84d855efe6d4a22ff929a7a7a984e448d23871e09b88a0bc3f3b7da55dd2edfb5a6daa102819ff50cd4dccd0a95d2f27354668065d4a56c31fb18b92b2a8db2c6453baa9333aea6eabb1bd6411d584dd5900262057a707f81cc5137dbdd9ac1079bb98da78a8e4bd1b2e0546c2b3d956fcc280d37d855e31f1e4315b387a742280f057f3219eae512884ae7ec4d2e3a72265b1d0163fbcbf616b2e289b0eaf9c63437d50b7b50ce408f5b4562f2abf510c19f5e8a0ace264db6e0f2a69a7d0b4a5e62a2b964f08c8ffe9c295f5773bdd7fab054a13822d428fae28ae5e4adc9d9f6e4dffc457a3e49f0bcf62b32961c4667b60960452afd917fdd00d954fa30c8533e5629f90af85948dc1bad889f91832ddf9b738254c9e7939726c37ab4557c2ce363c1391816c467537b471e5985e8084c277b62be514922d352e20689eabb3eb91c343f36e77b152d5e85afd088f4d02e7024b248a7420f58c7ebbeb480cae39b56164f5acd37a4f56b3db6e1cc6b7c8c96cd3c44a69d9ac99175257bab7fd83c5b574b5c9702c0fd13a5b176c60f82d2dfff50c2af25d96e0f8d27ec818d499e479b9642aed4a4a0e6af5f14cc5e1299eabae055ef3c763d1e350e2d76e92cee47a4233368466a298afb4ca108a325d2a4f8b79f21ee7349c1c186ecd7897f9886cf27ec01b05388870484867f84bae2c016d04a3762241907c4de207798dd125a2cebb6c2982f779e04117bdd65cd7ff0361a59d3ec05f6d903b6d15554beefb6d40d96a0d4b37ae76c69c1b9592088b7db878f95abedcb5fd5423ed93df1b27d01a4dc9f4438e7c55f35b0aeb7395b08e1ecbf15cb2b61d043c0454aeaef2d487093fa0d7de3fc6caf084b6a0f15a5cb05d9340d4e6763983dc45b7828539c77a60d5e081a03fe29949d916392b6d989b4c8c047e3635a76ba88ac18a7a18ccff5c7e06b02a43d2dff169fa449739e382bd020e0963c14a9acae6b6561c722d2bda183f33ee6a904df0207f5b098e56335cc063f9640c4997f593218d502f6b382354c73979e93c4b1b2471965ffa5a0dc8ee8eca9f5697e7ef08dc0eefd9ad75cd4122194b450201dfd73cda46a7b2478df66129fbb9c75b774213f9615bd990f8d07501fed440fd25d6cb912b8ecfa678d887a4ee28677e6e0491d49efc7a3b34b9815c5c22983da280d0afde2324f5281bc8b796ddacfd82723bbd9aa34b0c96075b36848591e47b80086897846fa76d092bc8bc6200837bfb5545039f8602b7ea49f63c0c3b8317eeeb7612f8e818dde09e43c7da76fd2ff6847906a45da3d993e8eaed9fb3b1e579d8cc6900c89522aaeb0b4a80da1e66ab8dfd62dfe4e4d77a3a77e5bd669207c70aa8537dd6d80a647b0420d79531a7456052c3c989f0f08de3d343c40067680b39ece95a17aac8a622d1d5d95b38ca0f11d94e5b0a7634eef4055517ace79f0df1d7c172e0246abb2ab6b135ee1a38a3b84f86fd7c3caf178cd4446d0b554256ad45c657e1192070aba7df480f489ebdf9753a79ccbc6aa893913c5f1271f1c6035" + + +def public_key(kid): + scheme = KEYS[kid].get("scheme", "ed25519") + return mldsa.public_key(secret(kid)) if scheme == "ml-dsa-65" else crypto.ed25519_public(secret(kid)) + + +def seal(rec, kid): + """Sign a record with a fixture key under its scheme.""" + if KEYS[kid].get("scheme", "ed25519") == "ml-dsa-65": + return RC.seal_mldsa(rec, mldsa.keygen(secret(kid))[1], kid) + return RC.seal(rec, secret(kid), kid) + + +def roster(): + keys = [] + for kid, k in KEYS.items(): + scheme = k.get("scheme", "ed25519") + pub = public_key(kid) + keys.append({"id": kid, "person": {"name": k["name"]}, "role": k["role"], "scheme": scheme, + "public": base64.b64encode(pub).decode(), "did": crypto.did_key(scheme, pub), + "purposes": k["purposes"], "registered_at": "2026-09-01T00:00:00Z", "revoked_at": None}) + return {"format": "scienting-roster/1", "store": STORE, "keys": keys} + + +ROSTER = roster() +ROSTER_BY_ID = {k["id"]: k for k in ROSTER["keys"]} + + +def png(w, h, rgb): + """A tiny valid PNG, so a fixture can carry a real image asset.""" + raw = b"".join(b"\x00" + bytes(rgb) * w for _ in range(h)) + + def chunk(t, d): + return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d) & 0xFFFFFFFF) + + return (b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)) + + chunk(b"IDAT", zlib.compress(raw, 9)) + chunk(b"IEND", b"")) + + +# --- the shorthand of fixtures/src ------------------------------------------------ + + +def runs_of(parts, kids): + out = [] + for p in parts: + if isinstance(p, str): + out.append({"kind": "text", "text": p}) + elif "sup" in p or "sub" in p or "em" in p: + st = next(k for k in ("sup", "sub", "em") if k in p) + out.append({"kind": "text", "text": p[st], "style": [st]}) + elif "m" in p: + out.append({"kind": "math", "notation": "tex", "source": p["m"]}) + elif "t" in p: + out.append({"kind": "math", "notation": "typst", "source": p["t"]}) + elif "cite" in p: + out.append({"kind": "cite", "refs": p["cite"], "text": p["text"]}) + elif "xref" in p: + out.append({"kind": "xref", "target": p["xref"], "text": p["text"]}) + elif "fn" in p: + out.append({"kind": "fnmark", "footnote": p["fn"], "text": p["text"]}) + elif "link" in p: + out.append({"kind": "link", "url": p["link"], "text": p["text"]}) + elif "eq" in p: + e = p["eq"] + kids.append(_math_node("equation", e)) + out.append({"kind": "equation", "child": len(kids) - 1}) + else: + raise ValueError(p) + return out + + +def _math_node(kind, e): + n = {"kind": kind, "content": {"notation": "typst" if "typst" in e else "tex", "source": e.get("tex", e.get("typst"))}} + if "label" in e: + n["label"] = e["label"] + for k in ("name", "fidelity"): + if k in e: + n["_" + k if k == "name" else k] = e[k] + return n + + +def expand(s, page=None): + if isinstance(s, str): + s = {"s": [s]} + page = s.get("page", page) + if "s" in s: + kids = [] + n = {"kind": "sentence", "content": runs_of(s["s"], kids), "children": kids} + elif "p" in s: + n = {"kind": "paragraph", "children": [expand(x, page) for x in s["p"]]} + elif "row" in s: + n = {"kind": "row", "children": [expand(x, page) for x in s["row"]]} + if "header_path" in s: + n["attrs"] = {"header_path": s["header_path"]} + elif "c" in s: + n = {"kind": "cell", "content": runs_of(s["c"], []), + "attrs": {"column": s["col"], "rowspan": s.get("rowspan", 1), "colspan": s.get("colspan", 1), + "role": s.get("role", "data")}} + n["fidelity"] = s.get("fidelity", "F1") + else: + n = {"kind": s["kind"]} + if "label" in s: + n["label"] = s["label"] + kids = [] + if s["kind"] == "section": + n["attrs"] = {"level": s["level"]} + if "title" in s: + kids.append({"kind": "heading", "children": [expand({"s": [s["title"]], "fidelity": "F2"}, page)]}) + if s["kind"] == "table": + n["attrs"] = {"columns": [{"id": c["name"], "header_path": c["header_path"]} for c in s["columns"]]} + if s["kind"] == "panel": + n["attrs"] = {} + if "figure_text" in s: + n["attrs"]["figure_text"] = [dict(t) for t in s["figure_text"]] + if s["kind"] in ("reference", "authors", "keywords"): + n["content"] = runs_of(s["runs"], []) + if s["kind"] in MATH_KINDS: + n = _math_node(s["kind"], s) + for k in ("csl", "resolution"): + if k in s: + n["_" + k] = s[k] + kids += [expand(x, page) for x in s.get("children", [])] + n["children"] = kids + if "name" in s: + n["_name"] = s["name"] + if "fidelity" in s and n["kind"] in LEAVES: + n["fidelity"] = s["fidelity"] + n["_page"] = page + for c in n.get("children", []): + if c.get("_page") is None: + c["_page"] = page + return n + + +class Names: + """Local names (`@x`) and the IDs minted for them, per document, registered under the source's name.""" + + registry = {} + + def __init__(self, name, key): + self.name = name + self.key = key + self.ids = {} + Names.registry[name] = self + + def resolve(self, v): + if isinstance(v, str) and v.startswith("ext:"): + parts = v.split(":", 2) + other = Names.registry[parts[1]] + if len(parts) == 2: # `ext:<source>`: the document, qualified by the store + return STORE + "/" + other.key + return other.key + "#" + other.ids[parts[2]] + if isinstance(v, str) and v.startswith("@"): + return self.ids[v] + if isinstance(v, list): + return [self.resolve(x) for x in v] + return v + + +def resolve_refs(nodes, names): + for n in nodes: + if n["kind"] in RUN_KINDS: + out = [] + for r in n["content"]: + r = dict(r) + if r["kind"] == "cite": + r["refs"] = names.resolve(r["refs"]) + elif r["kind"] == "xref": + r["target"] = names.resolve(r["target"]) + elif r["kind"] == "fnmark": + r["footnote"] = names.resolve(r["footnote"]) + out.append(r) + n["content"] = out + a = n.get("attrs") + if a: + if "header_path" in a: + a["header_path"] = names.resolve(a["header_path"]) + if "column" in a: + a["column"] = names.resolve(a["column"]) + if "columns" in a: + a["columns"] = [{"id": names.resolve(c["id"]), "header_path": names.resolve(c["header_path"])} + for c in a["columns"]] + + +def mint_extras(key, nodes, names, used): + """Columns and figure-text items get IDs from the same minting rule, kinds `column` and `figure-text`.""" + doc = Doc(key, nodes) + seen = {} + + def mint(kind, th): + occ = seen.get((kind, th), 0) + seen[(kind, th)] = occ + 1 + nid = mint_node_id(key, kind, th, occ) + while nid in used: + occ += 1 + nid = mint_node_id(key, kind, th, occ) + used.add(nid) + return nid + + for n in nodes: + a = n.get("attrs", {}) + for c in a.get("columns", []): + if c["id"].startswith("@"): + th = H(norm(" ".join(hashing.plain(doc, names.ids[h]) for h in c["header_path"]))) + names.ids[c["id"]] = mint("column", th) + for t in a.get("figure_text", []): + t["id"] = mint("figure-text", H(norm(t["text"]))) + if "name" in t: + names.ids[t.pop("name")] = t["id"] + + +def flatten_spec(spec): + flat = [] + _flatten(copy.deepcopy(spec), None, 0, flat) + return flat + + +def establish(key, spec, names, used): + flat = flatten_spec(spec) + nodes = mint_ids(key, flat, used) + side = {} + for f, n in zip(flat, nodes): + if "_name" in f: + names.ids[f["_name"]] = n["id"] + side[n["id"]] = {k: v for k, v in f.items() if k.startswith("_")} + mint_extras(key, nodes, names, used) + resolve_refs(nodes, names) + return nodes, side + + +# --- geometry ----------------------------------------------------------------- + + +def page_layout(doc, side, src, wit_id, fps_override=None): + """Synthetic but consistent geometry: lines per page, fingerprints and boxes.""" + P = src["pages"] + size = P["size"] + npages = len(P["labels"]) + stamps = json.load(open(os.path.join(ROOT, "registry", "stamps", "scienting-stamps-1.json")))["rules"] + lines = {p: [] for p in range(1, npages + 1)} + boxes = {} + y = {p: 72.0 for p in lines} + for p, rh in P.get("running_head", {}).items(): + lines[int(p)].append({"text": rh, "box": [72.0, 40.0, 400.0, 50.0]}) + for nid in doc.preorder(): + n = doc.nodes[nid] + pg = side.get(nid, {}).get("_page") or 1 + if n["kind"] in ("sentence", "cell", "reference", "authors", "keywords") or ( + n["kind"] == "equation" and doc.nodes[n["parent"]]["kind"] != "sentence"): + text = norm(hashing.plain(doc, nid)) + lines[pg].append({"text": text}) + bx = [] + rest = len(text) + while True: + w = min(rest, 80) + bx.append([72.0, y[pg], round(72.0 + 5.85 * w, 2), round(y[pg] + 11.8, 2)]) + y[pg] = round(y[pg] + 13.95, 2) + rest -= 80 + if rest <= 0: + break + boxes[nid] = (pg, bx) + elif n["kind"] == "panel": + boxes[nid] = (pg, [[72.0, y[pg], 300.0, round(y[pg] + 150.0, 2)]]) + y[pg] = round(y[pg] + 160.0, 2) + pages = [] + images = {} + for nid, s in side.items(): + if "_image" in s: + images.setdefault(boxes[nid][0], []).append(s["_image"]) + for p in range(1, npages + 1): + ls = list(lines[p]) + if "stamp" in P: + ls.append({"text": P["stamp"], "box": [8.0, 200.0, 20.0, 600.0]}) + ls.append({"text": P["stamp2"], "box": [580.0, 200.0, 592.0, 600.0]}) + page_in = {"size": size, "lines": ls, "images": images.get(p, [])} + fp, removed = FP.fingerprint(page_in, stamps) + rec = {"witness": wit_id, "page": p, "page_fp": fp, "size": size, "page_label": P["labels"][p - 1], + "text_layer": True} + if removed: + rec["stamps_removed"] = removed + pages.append((rec, page_in)) + return pages, boxes + + +# --- packages ------------------------------------------------------------------- + + +def rights_record(kind): + base = {"format": "scienting-rights/1", "at": "2026-09-15T12:00:00Z"} + if kind == "open": + base.update({"license": {"spdx": "CC-BY-4.0", "url": "https://creativecommons.org/licenses/by/4.0/"}, + "basis": "open-license", + "uses": {"read": True, "tdm": True, "redistribute": True, "quote-public": True, + "accessible-copy": True, "ai": {p: True for p in RI.AI_PAIRS}}, + "asserted_by": {"by": "crossref", "evidence": [ + {"kind": "crossref-license", "doi": "10.5555/example.okafor.2025", + "url": "https://creativecommons.org/licenses/by/4.0/"}]}, + "valid_until": None}) + elif kind == "own": + base.update({"license": {"spdx": "CC-BY-4.0"}, "basis": "own-work", + "uses": {"read": True, "tdm": True, "redistribute": True, "quote-public": True, + "accessible-copy": True, "ai": {p: True for p in RI.AI_PAIRS}}, + "asserted_by": {"by": "ana", "evidence": [{"kind": "statement", "note": "The team's own draft."}]}, + "valid_until": None}) + else: + base.update({"license": {"text": "Publisher's subscription terms (fictional)."}, "basis": "subscription", + "uses": {"read": True, "tdm": True, "redistribute": False, "quote-public": False, + "accessible-copy": "unknown", + "ai": {"internal/local": True, "internal/tenancy": "unknown", + "internal/outside-no-retention": "unknown", "internal/outside": False, + "external/local": False, "external/tenancy": False, + "external/outside-no-retention": False, "external/outside": False}}, + "asserted_by": {"by": "ana", "evidence": [ + {"kind": "statement", "note": "The library's subscription terms, as the team read them (fictional)."}]}, + "valid_until": "2027-08-31T23:59:59Z"}) + return base + + +def crop_sha(name): + return H("crop of " + name + " at 300 dpi (synthetic)") + + +def node_record(n, values): + rec = {k: n[k] for k in ("id", "kind", "parent", "ord")} + for k in ("label", "attrs", "content", "withheld", "fidelity", "prov"): + if k in n and n[k] not in (None, {}, []): + rec[k] = n[k] + rec.update(values[n["id"]]) + return rec + + +def seal_receipts(spec, names, state_by_rev, final_state, key, wit_sha): + """Build and sign the receipts and revocations a source lists.""" + out = [] + by_name = {} + final_doc = final_state.doc() + final_vals = hashing.compute(final_doc) + for r in spec: + if "revoke" in r: + rec = {"format": "scienting-revocation/1", "receipt": by_name[r["revoke"]]["id"], "reason": r["reason"], + "by": r["by"], "at": r["at"]} + rec = RC.seal(rec, secret(r["by"]), r["by"]) + elif "qa_of" in r: + orig = by_name[r["qa_of"]] + seed = RC.make_seed(orig, secret(r["key"])) + sample = RC.sample(orig, seed) + hashes = dict((nid, h) for nid, h in orig["nodes"]) + errs = [{"node": names.ids[e["node"]], **{k: v for k, v in e.items() if k != "node"}} for e in r["errors"]] + rec = {"format": "scienting-receipt/1", "doc": key, "rev": orig["rev"], "level": orig["level"], + "scope": "qa:" + orig["id"], "nodes": [[nid, hashes[nid]] for nid in sample], + "evidence": [{"kind": "crop", "node": nid, "sha256": crop_sha(nid)} for nid in sample], + "by": r["by"], "at": r["at"], + "qa": {"of": orig["id"], "key": r["key"], "seed": base64.b64encode(seed).decode(), "rate": "0.05", + "minimum": 10, "sample": sample, "errors": errs}} + rec = RC.seal(rec, secret(r["by"]), r["by"]) + else: + rev = r.get("rev", final_state.rev) + st = state_by_rev[rev] + vals = hashing.compute(st.doc()) if rev != final_state.rev else final_vals + ids = sorted(names.ids[x] for x in r["nodes"]) + scope = r["scope"] + if scope.startswith("section:@"): + scope = "section:" + names.ids[scope[8:]] + rec = {"format": "scienting-receipt/1", "doc": key, "rev": rev, "level": r["level"], "scope": scope, + "nodes": [[i, vals[i]["node_hash"]] for i in ids], + "evidence": [{"kind": "crop", "node": i, "sha256": crop_sha(i)} for i in ids] + + [{"kind": "witness", "sha256": wit_sha}], + "by": r["by"], "at": r["at"]} + rec = RC.seal(rec, secret(r["by"]), r["by"]) + by_name[r["name"]] = rec + out.append(rec) + out.sort(key=lambda x: (x["at"], x["id"])) + return out, by_name + + +def build_document(src, used=None, extra_files=None): + # The keys are minted, never written by hand (spec/02 §2.4): the work key from the work's identity and its + # metadata, the document key from the work key and the version. + d = src["document"] + wkey = K.work_key(d["work"].get("same_as"), d["meta"]) + key = K.document_key(wkey, d["version"]) + d["key"], d["work"]["key"] = key, wkey + names = Names(src.get("name", key), key) + used = used if used is not None else set() + spec = expand(src["tree"]) + nodes, side = establish(key, spec, names, used) + aliases = [{"id": a, "kind": "alias", "successor": names.ids[t]} + for a, t in sorted(src.get("legacy_aliases", {}).items())] + state = CO.State(key, nodes, aliases) + states = {0: state} + records = [] + for c in src.get("corrections", []): + c = copy.deepcopy(c) + crop = c.pop("crop", None) + new_name = c.pop("new_name", None) + before = c.pop("before", None) + c["evidence"] = [{"kind": "crop", "sha256": crop_sha(names.ids.get(crop, crop))}] if crop else [ + {"kind": "person", "by": "ana", "note": "Read against the page."}] + c["author"] = {"key": "ana"} + for k in ("target", "parent", "place_after", "with"): + if k in c: + c[k] = names.resolve(c[k]) + if "node" in c: + nspec = expand(c["node"]) + flat = flatten_spec(nspec) + pre = mint_ids(key, flat, state.used_ids()) + for f, n in zip(flat, pre): + if "_name" in f: + names.ids[f["_name"]] = n["id"] + c["node"] = _strip_private(nspec, names) + if before is not None: + d = state.doc() + c["offset"] = hashing.plain(d, c["target"]).index(before) + state, rec = CO.apply(state, c, store=SCHEMAS) + if new_name: + names.ids[new_name] = rec["created"][0] + records.append(rec) + states[state.rev] = state + # A corrected leaf was checked against the page image: it is F1 at most until corroborated again. + final = state + touched = set() + for rec in records: + if any(e["kind"] == "crop" for e in rec["evidence"]): + touched |= set(rec["touched"]) | set(rec.get("created", [])) + for n in final.nodes: + if n["id"] in touched and n["kind"] in LEAVES: + n["fidelity"] = "F1" + for n in final.nodes: + if n["kind"] in LEAVES and "fidelity" not in n: + n["fidelity"] = "F1" + return key, names, side, final, states, records + + +def _strip_private(spec, names): + out = {k: v for k, v in spec.items() if not k.startswith("_") and k != "children"} + if out["kind"] == "row" and "attrs" in out: + out["attrs"] = {"header_path": names.resolve(out["attrs"]["header_path"])} + if out["kind"] == "cell": + out["attrs"] = dict(out["attrs"], column=names.resolve(out["attrs"]["column"])) + if spec.get("children"): + out["children"] = [_strip_private(c, names) for c in spec["children"]] + return out + + +def package_files(src, key, names, side, final, records, receipts=None, roster_rec=None, witnesses=None, + pages=None, boxes=None, extra=None, absent=()): + doc = final.doc() + vals = hashing.compute(doc) + nodes = [node_record(doc.nodes[nid], vals) for nid in doc.preorder()] + files = {} + files["nodes.jsonl"] = jsonl(nodes) + if pages: + files["pages.jsonl"] = jsonl([p for p, _ in sorted(pages, key=lambda x: (x[0]["witness"], x[0]["page"]))]) + locs = [] + fps = {p["page"]: p for p, _ in pages} + pos = {nid: i for i, nid in enumerate(doc.preorder())} + for nid, (pg, bx) in boxes.items(): + if nid in doc.nodes: + locs.append({"node": nid, "page_fp": fps[pg]["page_fp"], "page": pg, + "page_label": fps[pg]["page_label"], "boxes": bx}) + locs.sort(key=lambda l: (pos[l["node"]], l["page"], l["page_fp"])) + if locs: + files["locations.jsonl"] = jsonl(locs) + refs = [] + for nid in doc.preorder(): + s = side.get(nid, {}) + if doc.nodes[nid]["kind"] == "reference": + r = {"node": nid, "label": doc.nodes[nid].get("label")} + if "_csl" in s: + r["csl"] = s["_csl"] + res = s.get("_resolution", {"type": "none"}) + r["resolution"] = {k: names.resolve(v) for k, v in res.items()} + refs.append({k: v for k, v in r.items() if v is not None}) + if refs: + files["references.jsonl"] = jsonl(refs) + if records: + files["corrections.jsonl"] = jsonl(records) + ids = sorted(final.ids, key=lambda e: (0 if e["kind"] == "alias" else 1, e.get("rev", 0), e["id"])) + if ids: + files["ids.jsonl"] = jsonl(ids) + if receipts: + files["receipts.jsonl"] = jsonl(receipts) + if roster_rec: + files["roster.json"] = (jcs.dumps(roster_rec) + "\n").encode() + files["witnesses.json"] = (jcs.dumps({"witnesses": witnesses}) + "\n").encode() + files["provenance.json"] = (jcs.dumps({ + "tools": [{"name": "paperspec tools/build.py", "version": VERSION}], + "stages": [{"stage": "hand", "processor": "local", "tool": "paperspec tools/build.py"}], + "note": "Built by hand for the conformance suite; every reading is synthetic."}) + "\n").encode() + levels = RC.effective_levels(nodes, vals, receipts or [], ROSTER_BY_ID if roster_rec else {}) + d = dict(src["document"]) + d = {"format": "scienting-doc/1", **d} + d.update({"hashing": {"scheme": "plain", "algorithm": "sha-256"}, "root": vals[doc.root]["node_hash"], "rev": final.rev, + "history": crypto.history_root(history_items(records or [])), + "counts": {"nodes": len(nodes), "leaves": sum(1 for n in nodes if n["kind"] in LEAVES)}, + "fidelity": RC.distribution(levels)}) + d["meta_hash"] = hashing.meta_hash(d) + files["document.json"] = (jcs.dumps(d) + "\n").encode() + if extra: + files.update(extra) + return files, nodes, vals, d + + +def build_hale(out): + src = json.load(open(os.path.join(ROOT, "fixtures", "src", "hale2026harmonic.json"))) + src["name"] = "hale2026harmonic" + image = png(4, 3, (40, 90, 160)) + image_sha = sha256_hex(image) + key, names, side, final, states, records = build_document(src) + side[names.ids["@pa"]]["_image"] = image_sha + doc = final.doc() + pa = doc.nodes[names.ids["@pa"]] + pa["attrs"]["image"] = {"sha256": image_sha, "media_type": "image/png", "native": True} + pa["attrs"]["crop"] = {"sha256": crop_sha("panel a"), "media_type": "image/png", "dpi": 300} + P = src["pages"] + wsha = H(P["witness"]["sha_seed"]) + wid = witness_id(wsha) + for n in final.nodes: + if n["kind"] in LEAVES: + n["prov"] = {"witnesses": [wid], "backend": "docling (illustrative)"} + if n.get("fidelity") == "F2": + n["prov"]["corroborated_by"] = [wid] + pages, boxes = page_layout(final.doc(), side, src, wid) + p2 = [p for p, _ in pages if p["page"] == 2][0] + for t in pa["attrs"]["figure_text"]: + t["page_fp"] = p2["page_fp"] + t["boxes"] = [[90.0, 300.0, 140.0, 310.0]] + witnesses = [{"id": wid, "sha256": wsha, "size": P["witness"]["size"], "kind": "pdf", "media_type": "application/pdf", + "pages": len(P["labels"]), "text_layer": True, "version_label": "version of record", + "origin": {"source": "publisher", "doi": "10.5555/example.hale.2026", "retrieved_at": "2026-10-01T08:00:00Z"}, + "rights": rights_record("subscription")}] + receipts, by_name = seal_receipts(src["receipts"], names, states, final, key, wsha) + # The dataset reported from Table 1. + final_doc = final.doc() + vals = hashing.compute(final_doc) + rows = [("ct-ct", "CT–CT", "@cc"), ("ct-hc", "CT–HC", "@ch2"), ("ow-hw", "OW–HW", "@ow")] + csv = ["key,bond,set,k_r,r_eq"] + anchors = [] + for rk, bond, pre in rows: + for st, (kc, rc) in (("A", ("_ak", "_ar")), ("B", ("_bk", "_br"))): + kid, rid = names.ids[pre + kc], names.ids[pre + rc] + kv, rv = norm(hashing.plain(final_doc, kid)), norm(hashing.plain(final_doc, rid)) + row_key = rk + "-" + st.lower() + csv.append("%s,%s,%s,%s,%s" % (row_key, bond, st, kv, rv)) + for field, nid in (("k_r", kid), ("r_eq", rid)): + anchors.append({"resource": "bond-parameters", "row": row_key, "field": field, + "anchor": AN.make_anchor(final_doc, vals, nid, final.rev, store=STORE)}) + ds_id = "ds-hale-bond-params" + datapackage = {"format": "scienting-dataset/1", "id": ds_id, "name": "hale-bond-params", + "title": "Harmonic bond parameters reported in Table 1", + "resources": [{"name": "bond-parameters", "path": "data.csv", "format": "csv", "encoding": "utf-8", + "schema": {"fields": [ + {"name": "key", "type": "string"}, {"name": "bond", "type": "string"}, + {"name": "set", "type": "string"}, + {"name": "k_r", "type": "number", "unit": "kcal / mol / angstrom ** 2"}, + {"name": "r_eq", "type": "number", "unit": "angstrom", + "uncertainty": {"kind": "unknown"}}], + "primaryKey": "key"}, + "origin": {"kind": "reported", "anchors": "anchors.jsonl"}}]} + eq = names.ids["@eq1"] + mathml = ('<math display="block"><msub><mi>E</mi><mtext>bond</mtext></msub><mo>=</mo><mfrac><mn>1</mn><mn>2' + '</mn></mfrac><msub><mi>K</mi><mi>r</mi></msub><msup><mrow><mo>(</mo><mi>r</mi><mo>−</mo><msub><mi>r' + '</mi><mtext>eq</mtext></msub><mo>)</mo></mrow><mn>2</mn></msup></math>') + extra = { + "assets/%s.png" % image_sha: image, + "datasets/%s/datapackage.json" % ds_id: (jcs.dumps(datapackage) + "\n").encode(), + "datasets/%s/data.csv" % ds_id: ("\n".join(csv) + "\n").encode(), + "datasets/%s/anchors.jsonl" % ds_id: jsonl(anchors), + "derived/mathml.jsonl": jsonl([{"node": eq, "run": None, "tool": {"name": "hand", "version": "0"}, + "mathml": mathml}]), + } + absent = [{"path": "assets/%s.png" % crop_sha("panel a"), "sha256": crop_sha("panel a"), "size": 18213, + "present": False}] + files, nodes, vals, d = package_files(src, key, names, side, final, records, receipts, ROSTER, witnesses, pages, + boxes, extra, absent) + write(os.path.join(out, "fixtures", "packages", key), files, absent) + return {"src": src, "key": key, "names": names, "states": states, "final": final, "records": records, + "receipts": receipts, "by_name": by_name, "pages": pages, "files": files, "nodes": nodes, "values": vals, + "document": d, "witness": witnesses[0], "absent": absent} + + +def build_checks_only(out, hale): + """The same document exported to another machine of the team: text withheld, hashes keyed.""" + final = hale["final"] + doc = final.doc() + k = crypto.team_key(TEAM_SECRET) + keyed = hashing.compute(doc, hashing.Hasher(k)) + nodes = [] + for nid in doc.preorder(): + n = copy.deepcopy(doc.nodes[nid]) + if n["kind"] in LEAVES: + n.pop("content", None) + n["withheld"] = True + if n["kind"] == "panel": + n["attrs"].pop("figure_text", None) + nodes.append(node_record(n, keyed)) + f = dict(hale["files"]) + for p in ("corrections.jsonl", "receipts.jsonl", "roster.json", "derived/mathml.jsonl"): + f.pop(p, None) + for p in [p for p in f if p.startswith("datasets/")]: + f.pop(p) + f["nodes.jsonl"] = jsonl(nodes) + refs = [{"node": r["node"], "label": r["label"], "resolution": r["resolution"]} + for r in map(json.loads, f["references.jsonl"].decode().splitlines())] + f["references.jsonl"] = jsonl(refs) + d = dict(hale["document"]) + d.update({"policy": "checks-only", "hashing": {"scheme": "hmac-team", "algorithm": "sha-256", "key_id": crypto.key_id(k)}, + "root": keyed[doc.root]["node_hash"], "history": crypto.EMPTY_ROOT}) + d["meta_hash"] = hashing.meta_hash(d, hashing.Hasher(k)) + f["document.json"] = (jcs.dumps(d) + "\n").encode() + write(os.path.join(out, "fixtures", "packages", hale["key"] + ".checks-only"), f, hale["absent"]) + + +def build_simple(out, name, used=None): + src = json.load(open(os.path.join(ROOT, "fixtures", "src", name + ".json"))) + src["name"] = name + key, names, side, final, states, records = build_document(src) + witnesses = [] + pages = boxes = None + if "pages" in src: + P = src["pages"] + wsha = H(P["witness"]["sha_seed"]) + wid = witness_id(wsha) + jsha = H(P["jats"]["sha_seed"]) + jid = witness_id(jsha) + for n in final.nodes: + if n["kind"] in LEAVES: + n["prov"] = {"witnesses": [jid, wid], "backend": "jats reader (illustrative)", "corroborated_by": [wid]} + pages, boxes = page_layout(final.doc(), side, src, wid) + witnesses = [ + {"id": jid, "sha256": jsha, "size": P["jats"]["size"], "kind": "jats", "media_type": "application/xml", + "version_label": "version of record", + "origin": {"source": "repository", "doi": "10.5555/example.okafor.2025"}, "rights": rights_record("open")}, + {"id": wid, "sha256": wsha, "size": P["witness"]["size"], "kind": "pdf", "media_type": "application/pdf", + "pages": len(P["labels"]), "text_layer": True, "version_label": "version of record", + "origin": {"source": "publisher", "doi": "10.5555/example.okafor.2025"}, "rights": rights_record("open")}] + else: + T = src["typst"] + tsha = H(T["sha_seed"]) + tid = witness_id(tsha) + for n in final.nodes: + if n["kind"] in LEAVES: + n["prov"] = {"witnesses": [tid], "backend": "typst reader (illustrative)"} + witnesses = [{"id": tid, "sha256": tsha, "size": T["size"], "kind": "typst", "media_type": "application/zip", + "version_label": "draft 3", "origin": {"source": "team"}, "rights": rights_record("own")}] + files, nodes, vals, d = package_files(src, key, names, side, final, records, None, None, witnesses, pages, boxes) + write(os.path.join(out, "fixtures", "packages", key), files) + return {"key": key, "names": names, "final": final, "files": files, "values": vals, "src": src} + + +# --- the tiny document used for corrections vectors and invalid packages ----------------- + +TINY = {"name": "tiny2026example", + "document": {"kind": "article", "work": {"same_as": ["doi:10.5555/example.tiny.2026"]}, + "version": {"type": "version-of-record"}, "relations": [], + "meta": {"title": "A tiny example", "author": [{"family": "Tiny", "given": "T."}], + "issued": {"date-parts": [[2026]]}}, + "language": "en", "license": {"spdx": "CC0-1.0"}, "policy": "full"}, + "tree": {"kind": "document", "children": [ + {"kind": "section", "name": "@sec", "label": "1", "level": 1, "title": "Results", "children": [ + {"name": "@p1", "p": [ + {"name": "@a", "s": ["The value is 42.0 at 300 K."], "fidelity": "F2"}, + {"name": "@b", "s": ["See ", {"xref": "@t", "text": "Table 1"}, " and the note.", {"cite": ["@r"], "text": "1"}], + "fidelity": "F2"}]}, + {"name": "@p2", "p": [{"name": "@c", "s": ["A second paragraph."], "fidelity": "F2"}, + {"name": "@d", "s": ["It ends here."], "fidelity": "F2"}]}, + {"kind": "table", "name": "@t", "label": "Table 1", + "columns": [{"name": "@cx", "header_path": ["@hx"]}, {"name": "@cy", "header_path": ["@hy"]}], + "children": [ + {"kind": "table-head", "children": [{"row": [ + {"name": "@hx", "c": ["x"], "role": "column-header", "col": "@cx"}, + {"name": "@hy", "c": ["y"], "role": "column-header", "col": "@cy"}]}]}, + {"kind": "table-body", "name": "@tb", "children": [ + {"name": "@row1", "header_path": ["@x1"], "row": [ + {"name": "@x1", "c": ["1"], "role": "row-header", "col": "@cx"}, + {"name": "@y1", "c": ["2.5"], "col": "@cy"}]}]}]}]}, + {"kind": "back", "children": [{"kind": "references", "children": [ + {"kind": "reference", "name": "@r", "label": "1", "runs": ["1. An Example, 2020."], + "resolution": {"type": "none"}, "fidelity": "F2"}]}]}]}} + + +def tiny_package(out_dir, receipts=True): + src = copy.deepcopy(TINY) + key, names, side, final, states, records = build_document(src) + wsha = H("tiny2026example: a file (synthetic)") + wit = [{"id": witness_id(wsha), "sha256": wsha, "size": 1000, "kind": "pdf", "media_type": "application/pdf", + "pages": 1, "origin": {"source": "author"}, "rights": rights_record("own")}] + recs = None + if receipts: + recs, _ = seal_receipts([{"name": "t1", "by": "ana", "level": "F3", "scope": "all", "at": "2026-10-11T12:00:00Z", + "nodes": ["@a", "@b", "@c", "@d", "@x1", "@y1", "@hx", "@hy", "@r"]}], + names, states, final, key, wsha) + files, nodes, vals, d = package_files(src, key, names, side, final, records, recs, ROSTER if receipts else None, + wit) + if out_dir: + write(out_dir, files) + return {"key": key, "names": names, "final": final, "files": files, "values": vals} + + +# --- vectors -------------------------------------------------------------------- + + +def wv(out, name, cases): + path = os.path.join(out, "vectors", name) + with open(path, "wb") as f: + f.write(jsonl(cases)) + + +def sentence_doc(runs, key="vectors"): + """A one-sentence document, so projections of runs can be computed with the node functions.""" + nodes = [{"id": "aaaaaaa", "kind": "document", "parent": None, "ord": 0}, + {"id": "bbbbbbb", "kind": "section", "parent": "aaaaaaa", "ord": 0, "attrs": {"level": 1}}, + {"id": "ccccccc", "kind": "paragraph", "parent": "bbbbbbb", "ord": 0}, + {"id": "ddddddd", "kind": "sentence", "parent": "ccccccc", "ord": 0, "content": runs}] + return Doc(key, nodes), "ddddddd" + + +def projection_case(cid, runs, note=None): + doc, s = sentence_doc(runs) + strict, cx = hashing.strict(doc, s) + lossy = hashing.lossy_from_strict(strict) + plain = hashing.plain(doc, s) + c = {"id": cid, "runs": runs, "plain": plain, "normalized": norm(plain), "strict": strict, "lossy": lossy, + "complex": cx, "text_hash": H(norm(plain)), "match_hash": H(strict), "align_key": H(lossy)} + if note: + c["note"] = note + return c + + +T = lambda t, **kw: dict({"kind": "text", "text": t}, **({"style": kw["style"]} if "style" in kw else {})) # noqa: E731 +M = lambda s, n="tex": {"kind": "math", "notation": n, "source": s} # noqa: E731 + + +def parse_doubles(text): + """Parse JSON as an ECMAScript engine does: every number is an IEEE 754 double.""" + return json.loads(text, parse_int=lambda x: int(x) if abs(int(x)) <= 2**53 else float(x)) + + +def vectors(out, hale, tiny): + # Canonical JSON. + cj = [ + ("sort-utf16", '{"\\u20ac": 1, "\\ud83d\\ude00": 2, "a": 3, "\\ufb01": 4}'), + ("numbers", '[0, -0.0, 1.0, 100.0, 72.10, 1E21, 1e-7, 0.000001, 123456789012345678901, -2.5e-5, 4.50e2]'), + ("escapes", '{"s": "tab\\tnl\\ncr\\rq\\"bs\\\\ctl\\u0001del\\u007fnbsp\\u00a0slash\\/"}'), + ("nested", '{ "b" : [ true , false , null ] , "a" : { "z" : "" , "y" : [ ] } }'), + ("strings-stay-unnormalized", '{"cafe\\u0301": "e\\u0301", "caf\\u00e9": "\\u00e9"}'), + ] + wv(out, "canonical-json.jsonl", [{"id": i, "input_json": t, "output": jcs.dumps(parse_doubles(t))} for i, t in cj]) + # Normalization for hashing. + ns = [("nfc", "cafe\u0301"), ("collapse", "a \t\n b"), ("trim", "\u00a0 a b \u3000"), + ("angstrom-sign", "1.5 \u212b"), ("nbsp-thin", "300\u2009K and 10\u00a0mol"), + ("zero-width-kept", "a\u200bb"), ("ligature-kept", "\ufb01t"), ("micro-kept", "5 \u00b5m"), + ("line-separator", "one\u2028two")] + wv(out, "normalize.jsonl", [{"id": i, "input": s, "output": norm(s), "sha256": H(norm(s))} for i, s in ns]) + # IDs. + idc = [] + for doc_key, kind, th, occ in [("cornell1995second", "sentence", H("A sentence."), 0), + ("cornell1995second", "sentence", H("A sentence."), 1), + ("cornell1995second.si", "sentence", H("A sentence."), 0), + (hale["key"], "cell", H("310.0"), 0), + (hale["key"], "column", H("Set A $K_r$ (kcal mol⁻¹ Å⁻²)"), 0)]: + payload = jcs.dumps(["scienting-id/1", doc_key, kind, th, occ]) + idc.append({"id": "mint-%s-%s-%d" % (doc_key, kind, occ), "doc": doc_key, "kind": kind, "text_hash": th, + "occurrence": occ, "payload": payload, "sha256": H(payload), + "node_id": mint_node_id(doc_key, kind, th, occ)}) + for hx in ("00" * 32, "ff" * 32, H("x")): + idc.append({"id": "letter-first-" + hx[:8], "digest": hx, "node_id": letter_first(bytes.fromhex(hx), 7), + "record_id": record_id(hx)}) + wv(out, "ids.jsonl", idc) + # Notation. + notes = [("tex", "H_2O"), ("tex", "_2"), ("tex", "\\mathrm{H}_{2}\\mathrm{O}"), ("typst", "H_2 O"), + ("typst", "upright(H)_2 upright(O)"), ("tex", "\\mathrm{cm}^{-1}"), ("typst", "\"cm\"^(-1)"), + ("tex", "10^{-3}"), ("typst", "10^(-3)"), ("tex", "K_r"), ("tex", "K_{\\mathrm{r}}"), ("typst", "K_r"), + ("tex", "\\alpha_i"), ("tex", "\\alpha_{i}"), ("tex", "x'_1"), ("tex", "x^{\\prime}"), + ("tex", "T = 300\\,\\mathrm{K}"), ("tex", "-1.5"), ("tex", "\\epsilon"), ("typst", "epsilon.alt"), + ("tex", "a \\cdot b"), ("typst", "a dot b"), ("tex", "a \\times b \\pm c"), ("tex", "\\left(x\\right)^2"), + ("typst", "(a+b)^2"), ("tex", "\\frac{a}{b}"), ("typst", "a/b"), ("tex", "\\sqrt{2}"), + ("tex", "\\mathbf{F}"), ("tex", "{ab}_2"), ("tex", "x_1_2"), ("tex", "\\Delta G^\\circ"), + ("tex", "E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2"), ("typst", "E = K_r (r - r_\"eq\")^2"), + # A script after an empty group applies to the atom before it, or to an empty base (the isotope idiom). + ("tex", "{}^{14}C"), ("tex", "x{}^2"), ("tex", "{}_2"), ("tex", "\\left)x\\right("), + # Letters are the Latin and Greek blocks: a fullwidth or modifier letter is complex, a Coptic letter too. + ("tex", "A"), ("tex", "ʰ"), ("tex", "Ϣ"), ("tex", "ἀω")] + wv(out, "notation.jsonl", [{"id": "%s:%s" % (n, s), "notation": n, "source": s, "canonical": fold_math(n, s)} + for n, s in notes]) + # Projections. + pc = [ + projection_case("h2o-math", [T("The solvent is "), M("H_2O"), T(".")]), + projection_case("h2o-split-math", [T("The solvent is H"), M("_2"), T("O.")]), + projection_case("h2o-mathrm", [T("The solvent is "), M("\\mathrm{H}_{2}\\mathrm{O}"), T(".")]), + projection_case("h2o-sub", [T("The solvent is H"), T("2", style=["sub"]), T("O.")]), + projection_case("h2o-unicode", [T("The solvent is H\u2082O.")]), + projection_case("h2o-typst", [T("The solvent is "), M("H_2 O", "typst"), T(".")]), + projection_case("wavenumber-unicode", [T("A band near 1595 cm\u207b\u00b9.")]), + projection_case("wavenumber-sup", [T("A band near 1595 cm"), T("-1", style=["sup"]), T(".")]), + projection_case("wavenumber-math", [T("A band near 1595 "), M("\\mathrm{cm}^{-1}"), T(".")]), + projection_case("wavenumber-typst", [T("A band near 1595 "), M("\"cm\"^(-1)", "typst"), T(".")]), + projection_case("milli-unicode", [T("Values below 10\u207b\u00b3 were dropped.")]), + projection_case("milli-sup", [T("Values below 10"), T("\u22123", style=["sup"]), T(" were dropped.")]), + projection_case("milli-math", [T("Values below "), M("10^{-3}"), T(" were dropped.")]), + projection_case("kr-math", [T("The constant "), M("K_r"), T(" is large.")]), + projection_case("kr-mathrm", [T("The constant "), M("K_{\\mathrm{r}}"), T(" is large.")]), + projection_case("kr-sub", [T("The constant K"), T("r", style=["sub"]), T(" is large.")]), + projection_case("kr-unicode", [T("The constant K\u1d63 is large.")]), + projection_case("ligature", [T("The \ufb01t is good.")]), + projection_case("no-ligature", [T("The fit is good.")]), + projection_case("micro-sign", [T("A 5 \u00b5m film.")]), + projection_case("greek-mu", [T("A 5 \u03bcm film.")]), + projection_case("lost-superscript", [T("A rate of 103 per second.")], "OCR lost the superscript."), + projection_case("superscript", [T("A rate of 10\u00b3 per second.")]), + projection_case("cite-mark", [T("The energy"), {"kind": "cite", "refs": [], "text": "3"}, T(" is low.")]), + projection_case("cite-as-text", [T("The energy3 is low.")]), + projection_case("complex", [T("The energy is "), M("\\frac{1}{2} k x^2"), T(" exactly.")]), + projection_case("hyphen-before-digit", [T("pages 10-20 and CT\u2013CT with 6-31G*")]), + projection_case("en-dash-before-digit", [T("pages 10\u201320 and CT-CT with 6\u201331G*")]), + projection_case("astral", [T("Let "), M("\U0001d465"), T(" vary.")]), + ] + groups = [ + {"id": "h2o", "same": "match_hash", + "cases": ["h2o-math", "h2o-split-math", "h2o-mathrm", "h2o-sub", "h2o-unicode", "h2o-typst"]}, + {"id": "wavenumber", "same": "match_hash", + "cases": ["wavenumber-unicode", "wavenumber-sup", "wavenumber-math", "wavenumber-typst"]}, + {"id": "milli", "same": "match_hash", "cases": ["milli-unicode", "milli-sup", "milli-math"]}, + {"id": "kr", "same": "match_hash", "cases": ["kr-math", "kr-mathrm", "kr-sub", "kr-unicode"]}, + {"id": "ligature", "same": "match_hash", "cases": ["ligature", "no-ligature"]}, + {"id": "micro", "same": "match_hash", "cases": ["micro-sign", "greek-mu"]}, + {"id": "103-align", "same": "align_key", "cases": ["lost-superscript", "superscript"]}, + {"id": "103-match", "differ": "match_hash", "cases": ["lost-superscript", "superscript"]}, + {"id": "cite-structure", "differ": "match_hash", "cases": ["cite-mark", "cite-as-text"]}, + {"id": "dashes-align", "same": "align_key", "cases": ["hyphen-before-digit", "en-dash-before-digit"]}, + {"id": "dashes-text", "differ": "text_hash", "cases": ["hyphen-before-digit", "en-dash-before-digit"]}, + ] + byid = {c["id"]: c for c in pc} + for g in groups: + vals = {byid[c][g.get("same") or g.get("differ")] for c in g["cases"]} + assert (len(vals) == 1) if "same" in g else (len(vals) == len(g["cases"])), g + wv(out, "projections.jsonl", pc) + wv(out, "projection-groups.jsonl", groups) + # Offsets. + off = [] + for cid, runs, span in [("bmp", [T("A sentence about H"), M("_2"), T("O.")], [18, 24]), + ("astral", [T("Let "), M("\U0001d465"), T(" vary with "), M("\U0001d466"), T(".")], [4, 7])]: + doc, s = sentence_doc(runs) + p = hashing.plain(doc, s) + from tools.oracle.text import cp_to_utf16 + off.append({"id": cid, "runs": runs, "plain": p, "span": span, "exact": p[span[0]:span[1]], + "utf16_span": [cp_to_utf16(p, span[0]), cp_to_utf16(p, span[1])], "code_points": len(p), + "utf16_units": cp_to_utf16(p, len(p))}) + wv(out, "offsets.jsonl", off) + # Five values on a small tree: the tiny document. + tnodes = [{k: v for k, v in n.items() if k not in ("text_hash", "match_hash", "align_key", "own_hash", "node_hash")} + for n in map(json.loads, tiny["files"]["nodes.jsonl"].decode().splitlines())] + tdoc = Doc(tiny["key"], tnodes) + tv = hashing.compute(tdoc) + own = {nid: hashing.own_content(tdoc, nid, lambda x: tv[x]["text_hash"]) for nid in tdoc.order} + wv(out, "hashes.jsonl", [{"id": "tiny2026example", "doc": tiny["key"], "nodes": tnodes, + "own_content": own, "values": tv}]) + # Addresses. The example keys are real work keys: Cornell et al. (1995) by its DOI, a fictional preprint. + cornell = "cornell1995second-" + K.suffix("doi:10.1021/ja00124a002") + dong = "dong2026machine-" + K.suffix("doi:10.5555/example.dong.2026") + ad = [("plain", cornell + "#k3m9q2a"), ("pinned", cornell + "#k3m9q2a@4f1a0c"), + ("span", cornell + "#k3m9q2a@4f1a0c[12:57]"), ("store", "smithlab/" + cornell + "#k3m9q2a"), + ("span-no-pin", dong + ".v2#k3m9q2a[0:0]"), ("si", cornell + ".si#m2x8p4d"), + ("alias", cornell + "#b-p03-text-004"), ("bad-reversed", cornell + "#k3m9q2a[57:12]"), + ("bad-pin", cornell + "#k3m9q2a@4F1A0C"), ("bad-leading-zero", "k-0000#k3m9q2a[01:2]"), + ("bad-no-node", cornell + "#"), ("bad-upper-key", "Cornell1995-k3f9#k3m9q2a"), + ("bad-two-stores", "a/b/c-0000#k3m9q2a"), ("bad-pin-length", "k-0000#k3m9q2a@4f1a"), + ("bad-no-hash", "cornell1995second#k3m9q2a"), ("bad-hash-alphabet", "cornell1995second-k3fi#k3m9q2a"), + ("bad-short-hash", "cornell1995second-k3f#k3m9q2a")] + wv(out, "addresses.jsonl", [{"id": i, "address": a, "parsed": AN.parse_address(a)} for i, a in ad]) + # Keyed hashes. + k = crypto.team_key(TEAM_SECRET) + fps = [p["page_fp"] for p, _ in hale["pages"]] + pk = crypto.page_key(fps, "layer:smithlab/kp4m2x7q") + text = "310.0" + keyed = [ + {"id": "team-key", "secret": TEAM_SECRET.hex(), "key": k.hex(), "key_id": crypto.key_id(k)}, + {"id": "team-hmac-text", "key": k.hex(), "text": text, "text_hash_plain": H(text), + "text_hash_keyed": hashing.Hasher(k)(text)}, + {"id": "page-hashes", "page_fps": fps, "page_hashes": [crypto.page_hash(f) for f in fps]}, + {"id": "page-key", "page_fps": fps, "context": "layer:smithlab/kp4m2x7q", "key": pk.hex(), + "quote": "310.0", "quote_mac": hashing.Hasher(pk)(norm(text))}, + {"id": "non-holder", "note": "Without the pages, a guess hashes to the plain value, which the export never " + "carries; with one page changed, the key differs.", + "guess": text, "guess_sha256": H(text), + "wrong_page_fps": [fps[0], H("another page")], + "wrong_key": crypto.page_key([fps[0], H("another page")], "layer:smithlab/kp4m2x7q").hex(), + "quote_mac": hashing.Hasher(pk)(norm(text))}, + ] + assert keyed[4]["wrong_key"] != pk.hex() and keyed[4]["guess_sha256"] != keyed[4]["quote_mac"] + wv(out, "keyed.jsonl", keyed) + # Fingerprints: two downloads of one page, stamped differently. + stamps = json.load(open(os.path.join(ROOT, "registry", "stamps", "scienting-stamps-1.json")))["rules"] + _, p1 = hale["pages"][0] + body = [l for l in p1["lines"] if "box" not in l] + acs1 = dict(p1) + acs2 = dict(p1, lines=body + [ + {"text": "Downloaded via EXAMPLE PHARMA INC on March 2, 2027 at 09:14:55 (UTC).", "box": [8.0, 210.0, 20.0, 590.0]}, + {"text": "See https://pubs.acs.org/sharingguidelines for options on how to legitimately share published articles.", + "box": [580.0, 200.0, 592.0, 600.0]}]) + wiley = {"size": [595.276, 841.89], "images": [H("figure 2 image stream (synthetic)")], "lines": [ + {"text": "Results"}, {"text": "The fitted slope is 0.42 \u00b1 0.03 per kelvin."}, + {"text": "Downloaded from https://onlinelibrary.wiley.com/doi/10.5555/example.wiley by Example University, " + "Wiley Online Library on [11/10/2026]. See the Terms and Conditions (https://onlinelibrary.wiley.com/" + "terms-and-conditions) on Wiley Online Library for rules of use.", "box": [580.0, 100.0, 592.0, 740.0]}]} + wiley2 = dict(wiley, lines=wiley["lines"][:2] + [ + {"text": "Downloaded from https://onlinelibrary.wiley.com/doi/10.5555/example.wiley by Example Pharma Inc, " + "Wiley Online Library on [02/03/2027].", "box": [580.0, 100.0, 592.0, 740.0]}, + {"text": "See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online " + "Library for rules of use.", "box": [580.0, 60.0, 592.0, 99.0]}]) + changed = dict(acs1, lines=[dict(l, text=l["text"].replace("1595", "1594")) for l in acs1["lines"]]) + scan = {"size": [612.4, 791.6], "lines": [], "images": [H("scanned page image (synthetic)")]} + fpc = [] + for cid, pg in [("acs-download-1", acs1), ("acs-download-2", acs2), ("acs-changed-text", changed), + ("wiley-download-1", wiley), ("wiley-download-2", wiley2), ("scanned", scan)]: + fp, removed = FP.fingerprint(pg, stamps) + kept = [l["text"] for l in pg["lines"] if not FP.is_stamp(l, pg["size"], stamps)] + fpc.append({"id": cid, "page": pg, "rules": "scienting-stamps-1", "removed": removed, + "text": FP.fp_text(" ".join(kept)), "page_fp": fp}) + assert fpc[0]["page_fp"] == fpc[1]["page_fp"] != fpc[2]["page_fp"] and fpc[3]["page_fp"] == fpc[4]["page_fp"] + wv(out, "fingerprints.jsonl", fpc) + # Merkle roots. + mk = [] + for n in (1, 2, 3, 4, 5, 7): + items = [["node", mint_node_id("m", "sentence", H(str(i)), 0), H("h%d" % i)] for i in range(n)] + mk.append({"id": "items-%d" % n, "items": items, "root": crypto.merkle_root(items)}) + wv(out, "merkle.jsonl", mk) + # Signatures. + r1 = hale["by_name"]["r1"] + sk = bytes.fromhex("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + wv(out, "signatures.jsonl", [ + {"id": "rfc8032-test-1", "secret": sk.hex(), "public": crypto.ed25519_public(sk).hex(), "message": "", + "signature": crypto.ed25519_sign(sk, b"").hex()}, + {"id": "receipt-r1", "receipt": r1, "record_hash": RC.record_hash(r1), + "payload": RC.signing_payload(r1).decode(), "public": ROSTER_BY_ID["ana"]["public"], + "record_id": r1["id"]}, + {"id": "did-key-ed25519", "scheme": "ed25519", "public": crypto.ed25519_public(sk).hex(), + "did": crypto.did_key("ed25519", crypto.ed25519_public(sk))}, + {"id": "did-key-ml-dsa-65", "scheme": "ml-dsa-65", "public": mldsa.public_key(sk).hex(), + "did": crypto.did_key("ml-dsa-65", mldsa.public_key(sk))}, + # FIPS 204: NIST's ACVP key-generation case 26 for ML-DSA-65 (seed to public key), and our own + # deterministic signature over the empty message for the RFC 8032 test key used as a seed. + {"id": "ml-dsa-65-nist-keygen-26", + "seed": NIST_SEED, + "public": NIST_PK}, + {"id": "ml-dsa-65-sign-empty", "seed": sk.hex(), "public": mldsa.public_key(sk).hex(), "message": "", + "signature": mldsa.sign(mldsa.keygen(sk)[1], b"").hex()}]) + # Spot-checks. + q1 = hale["by_name"]["q1"] + wv(out, "spotcheck.jsonl", [{"id": "q1", "receipt": r1, "seed_payload": RC.seed_payload(r1).decode(), + "checker_public": ROSTER_BY_ID["ben-spot"]["public"], "seed": q1["qa"]["seed"], + "beta": vrf.proof_to_hash(base64.b64decode(q1["qa"]["seed"])).hex(), + "n": len(r1["nodes"]), "rate": "0.05", "minimum": 10, + "size": RC.sample_size(len(r1["nodes"])), "sample": q1["qa"]["sample"]}] + + [{"id": "size-%d" % n, "n": n, "rate": "0.05", "minimum": 10, "size": RC.sample_size(n)} + for n in (3, 10, 199, 200, 201, 3000)]) + # Bounds. + wv(out, "bounds.jsonl", [{"id": "k%d-n%d" % (kk, nn), "errors": kk, "sampled": nn, "confidence": "0.95", + "bound": RC.bound_string(kk, nn), "approx": round(RC.upper_bound(kk, nn), 9)} + for kk, nn in [(0, 10), (0, 300), (1, 10), (1, 300), (2, 50), (5, 100), (0, 1), (10, 10)]]) + # Keys (spec/02 §2.4): Scholar parts, identities and suffixes, including the cases paperstack pins. + attn = {"title": "Attention is all you need", "author": [{"family": "Vaswani", "given": "Ashish"}], + "issued": {"date-parts": [[2017]]}} + kc = [] + for cid, same_as, meta in [ + ("doi", ["doi:10.48550/arXiv.1706.03762"], attn), + ("openalex", ["openalex:W2963403868"], attn), + ("doi-before-arxiv", ["arxiv:1706.03762", "doi:10.48550/arXiv.1706.03762"], attn), + ("arxiv-only", ["arxiv:1706.03762"], attn), + ("url-is-not-an-identity", ["url:https://example.org/paper"], attn), + ("meta", [], {"title": "On the Origin of Species", "author": [{"family": "Darwin", "given": "Charles"}], + "issued": {"date-parts": [[1859]]}}), + ("doi-case", ["doi:10.1109/CVPR.2016.90"], {"title": "Deep Residual Learning for Image Recognition", + "author": [{"family": "He", "given": "Kaiming"}], + "issued": {"date-parts": [[2016]]}}), + ("accents", [], {"title": "A new method", "author": [{"literal": "M\u00fcller, J\u00fcrgen"}], + "issued": {"date-parts": [[2001]]}}), + ("apostrophe", [], {"title": "Don't stop", "author": [{"literal": "Conan O'Brien"}], + "issued": {"date-parts": [[2020]]}}), + ("name-suffix", [], {"title": "3D printing of bone", "author": [{"literal": "A. Smith Jr."}], + "issued": {"date-parts": [[2015]]}}), + ("only-stop-words", [], {"title": "The of a", "author": [{"family": "Lee", "given": "Jo"}], + "issued": {"date-parts": [[2019]]}}), + ("no-year", [], {"title": "Untitled", "author": [{"family": "Lee"}]}), + ("no-author", [], {"title": "Fluids", "issued": {"date-parts": [[2020]]}}), + ("non-latin-author", [], {"title": "Fluids", "author": [{"family": "\u5f20\u4f1f"}], "issued": {"date-parts": [[2020]]}}), + ("hale", hale["src"]["document"]["work"]["same_as"], hale["src"]["document"]["meta"]), + ]: + ident = K.identity(same_as, meta) + kc.append({"id": cid, "same_as": same_as, "meta": meta, "scholar": K.scholar_part(meta), "identity": ident, + "payload": K.SCHEME + ":" + ident, "sha256": H(K.SCHEME + ":" + ident), "suffix": K.suffix(ident), + "suffix_8": K.suffix(ident, 8), "key": K.work_key(same_as, meta)}) + hk = hale["document"]["work"]["key"] + for cid, version in [("version-of-record", {"type": "version-of-record"}), ("supplement", {"type": "supplement"}), + ("preprint-v2", {"type": "preprint", "seq": 2}), ("draft-v3", {"type": "draft", "seq": 3}), + ("erratum", {"type": "erratum"}), ("accepted-no-seq", {"type": "accepted"})]: + kc.append({"id": "document-" + cid, "work_key": hk, "version": version, "document_key": K.document_key(hk, version)}) + kc.append({"id": "collision", "same_as": attn and ["doi:10.48550/arXiv.1706.03762"], "meta": attn, + "taken": [K.work_key(["doi:10.48550/arXiv.1706.03762"], attn)], + "key": K.unique_work_key(["doi:10.48550/arXiv.1706.03762"], attn, {K.work_key(["doi:10.48550/arXiv.1706.03762"], attn)})}) + wv(out, "keys.jsonl", kc) + # Proofs (RFC 9162): inclusion for every item of the Merkle vectors, consistency for every prefix, and the + # example paper's correction history. + pf = [{"id": "empty-history", "kind": "root", "items": [], "root": crypto.history_root([])}] + for n in (1, 2, 3, 4, 5, 7): + items = [["node", mint_node_id("m", "sentence", H(str(i)), 0), H("h%d" % i)] for i in range(n)] + root = crypto.merkle_root(items) + for i in range(n): + pf.append({"id": "inclusion-%d-of-%d" % (i, n), "kind": "inclusion", "items": items, "index": i, "size": n, + "root": root, "leaf": crypto.leaf_hash(items[i]), "path": crypto.inclusion_path(items, i)}) + for m in range(n + 1): + pf.append({"id": "consistency-%d-to-%d" % (m, n), "kind": "consistency", "items": items, "from": m, "to": n, + "from_root": crypto.history_root(items[:m]), "to_root": root, + "path": crypto.consistency_proof(items, m)}) + hist = history_items(hale["records"]) + pf.append({"id": "hale-history-8-to-12", "kind": "consistency", "items": hist, "from": 8, "to": len(hist), + "from_root": crypto.history_root(hist[:8]), "to_root": crypto.history_root(hist), + "path": crypto.consistency_proof(hist, 8)}) + pf.append({"id": "hale-history-correction-5", "kind": "inclusion", "items": hist, "index": 4, "size": len(hist), + "root": crypto.history_root(hist), "leaf": crypto.leaf_hash(hist[4]), "path": crypto.inclusion_path(hist, 4)}) + wv(out, "proofs.jsonl", pf) + # The VRF (RFC 9381, ECVRF-EDWARDS25519-SHA512-TAI): the RFC's Example 16, two more inputs for its key, and + # the spot-check seed of the example paper's first receipt. + vv = [] + for cid, alpha in (("rfc9381-example-16", b""), ("rfc9381-key-alpha-72", b"\x72"), ("rfc9381-key-alpha-af82", b"\xaf\x82")): + pi = vrf.prove(sk, alpha) + vv.append({"id": cid, "secret": sk.hex(), "public": vrf.public_key(sk).hex(), "alpha": alpha.hex(), + "proof": pi.hex(), "beta": vrf.proof_to_hash(pi).hex()}) + seed = base64.b64decode(q1["qa"]["seed"]) + vv.append({"id": "ben-spot-seed-q1", "public": base64.b64decode(ROSTER_BY_ID["ben-spot"]["public"]).hex(), + "alpha": RC.seed_payload(r1).hex(), "proof": seed.hex(), "beta": vrf.proof_to_hash(seed).hex()}) + bad = bytearray(seed) + bad[40] ^= 1 + vv.append({"id": "tampered-challenge", "public": base64.b64decode(ROSTER_BY_ID["ben-spot"]["public"]).hex(), + "alpha": RC.seed_payload(r1).hex(), "proof": bytes(bad).hex(), "beta": None}) + vv.append({"id": "other-input", "public": base64.b64decode(ROSTER_BY_ID["ben-spot"]["public"]).hex(), + "alpha": (RC.seed_payload(r1) + b"x").hex(), "proof": seed.hex(), "beta": None}) + wv(out, "vrf.jsonl", vv) + # A checkpoint of the team's log (spec/23): every receipt and revocation of the example paper, then the roster. + entries = [LG.entry(r) for r in hale["receipts"]] + [LG.entry(ROSTER)] + note = LG.sign_checkpoint("scient.ing/log/smithlab", entries, [("ana", secret("ana")), ("wit", secret("wit"))]) + wv(out, "checkpoint.jsonl", [{"id": "smithlab", "origin": "scient.ing/log/smithlab", "entries": entries, + "root": LG.root(entries), "signers": ["ana", "wit"], "note": note, + "tiles": sorted(LG.tiles(entries))}]) + # Alignment. + def item(i, runs, container, context="paragraph"): + doc, s = sentence_doc(runs) + st, cx = hashing.strict(doc, s) + return {"id": i, "runs": runs, "strict": st, "lossy": hashing.lossy_from_strict(st), "complex": cx, + "container": container, "context": context} + A = [item("a1", [T("Methods")], "h", "heading"), + item("a2", [T("Every bond was scanned in steps of 0.01 \u00c5 around its minimum.")], "p1"), + item("a3", [T("where "), M("\\frac{a}{b}"), T(" is the bond length.")], "p1"), + item("a4", [T("The fitted rate is 10\u00b3 per second at room temperature.")], "p1"), + item("a5", [T("where "), M("\\frac{c}{d}"), T(" is the bond length.")], "p2"), + item("a6", [T("This sentence was dropped by the second reading entirely.")], "p2"), + item("a7", [T("The last sentence of the section is unique and long enough.")], "p2")] + B = [item("b1", [T("Methods")], "x", "paragraph"), + item("b2", [T("Every bond was scanned in steps of 0.01 \u00c5 around its minimum.")], "q1"), + item("b3", [T("where "), M("\\frac{a}{b}"), T(" is the bond length.")], "q1"), + item("b4", [T("The fitted rate is 103 per second at room temperature.")], "q2"), + item("b5", [T("where "), M("\\frac{c}{e}"), T(" is the bond length.")], "q2"), + item("b6", [T("A sentence only the second reading has, also long.")], "q2"), + item("b7", [T("The last sentence of the section is unique and long enough.")], "q2")] + wv(out, "alignment.jsonl", [{"id": "two-readings", "a": A, "b": B, "expect": AL.align(A, B)}]) + # Corrections, op by op, on the tiny document. + wv(out, "corrections.jsonl", corrections_vectors()) + # Anchor resolution against the hale package. + wv(out, "resolve.jsonl", resolve_vectors(hale)) + # Rights. + wv(out, "rights.jsonl", rights_vectors(hale)) + + +def corrections_vectors(): + tiny = tiny_package(None, receipts=False) + st0 = tiny["final"] + nm = tiny["names"].ids + crop = [{"kind": "crop", "sha256": crop_sha("tiny")}] + person = [{"kind": "person", "by": "ana"}] + base = {"author": {"key": "ana"}, "reason": "Vector.", "at": "2026-10-11T12:00:00Z"} + cases = [ + ("replace-digit", {"op": "replace", "target": nm["@a"], "find": "42.0", "replace": "42.5", "evidence": crop}), + ("replace-digit-no-crop", {"op": "replace", "target": nm["@a"], "find": "42.0", "replace": "42.5", "evidence": person}), + ("replace-word", {"op": "replace", "target": nm["@c"], "find": "second", "replace": "later", "evidence": person}), + ("replace-not-unique", {"op": "replace", "target": nm["@a"], "find": "0", "replace": "1", "evidence": crop}), + ("replace-runs", {"op": "replace", "target": nm["@a"], "find": "300 K", "replace": [ + {"kind": "math", "notation": "tex", "source": "300\\,\\mathrm{K}"}], "evidence": crop}), + ("insert-text", {"op": "insert", "target": nm["@d"], "run": 0, "offset": 8, "text": "only ", "evidence": crop}), + ("insert-text-no-crop", {"op": "insert", "target": nm["@d"], "run": 0, "offset": 8, "text": "only ", + "evidence": person}), + ("insert-text-bad-run", {"op": "insert", "target": nm["@d"], "run": 7, "offset": 0, "text": "x", + "evidence": crop}), + ("insert-node", {"op": "insert", "parent": nm["@p2"], "place_after": nm["@c"], + "node": {"kind": "sentence", "content": [{"kind": "text", "text": "A dropped sentence."}]}, + "evidence": crop}), + ("delete", {"op": "delete", "target": nm["@p2"], "evidence": person}), + ("delete-digits-no-crop", {"op": "delete", "target": nm["@p1"], "evidence": person}), + ("split", {"op": "split", "target": nm["@a"], "offset": 13, "evidence": person}), + ("split-inside-xref", {"op": "split", "target": nm["@b"], "offset": 6, "evidence": person}), + ("merge", {"op": "merge", "target": nm["@c"], "with": nm["@d"], "joiner": " ", "evidence": person}), + ("merge-not-adjacent", {"op": "merge", "target": nm["@a"], "with": nm["@c"], "evidence": person}), + ("move", {"op": "move", "target": nm["@d"], "parent": nm["@p1"], "place_after": None, "evidence": person}), + ("move-after-itself", {"op": "move", "target": nm["@d"], "parent": nm["@p2"], "place_after": nm["@d"], + "evidence": person}), + ("reclassify", {"op": "reclassify", "target": nm["@p2"], "kind": "footnote", "evidence": person}), + ("reclassify-blocks", {"op": "reclassify", "target": nm["@p2"], "kind": "quote", "evidence": person}), + ("reclassify-bad", {"op": "reclassify", "target": nm["@a"], "kind": "paragraph", "evidence": person}), + ("relabel-section", {"op": "relabel", "target": nm["@sec"], "label": "2", "evidence": crop}), + ("relabel-remove", {"op": "relabel", "target": nm["@sec"], "label": None, "evidence": crop}), + ("relabel-digit-no-crop", {"op": "relabel", "target": nm["@t"], "label": "Table 2", "evidence": person}), + ("set-colspan", {"op": "set", "target": nm["@y1"], "attr": "colspan", "value": 2, "evidence": person}), + ("set-bad-value", {"op": "set", "target": nm["@y1"], "attr": "colspan", "value": "2", "evidence": person}), + ("set-not-settable", {"op": "set", "target": nm["@y1"], "attr": "level", "value": 2, "evidence": person}), + ("insert-node-junk", {"op": "insert", "parent": nm["@p2"], "place_after": nm["@c"], + "node": {"kind": "sentence", "content": [{"kind": "text", "text": "Junk."}], "foo": 1}, + "evidence": crop}), + ("delete-header-cell", {"op": "delete", "target": nm["@hx"], "evidence": person}), + # A model proposed this one, so its author names the model, by weights and prompt, and the run. + ("replace-by-model", {"op": "replace", "target": nm["@c"], "find": "second", "replace": "later", "evidence": person, + "author": {"model": MODEL, "run": "illustrative-run-7"}}), + ] + out = [] + vals0 = hashing.compute(st0.doc()) + before = [dict(n, **vals0[n["id"]]) for n in st0.nodes] + for cid, c in cases: + c = dict(base, **c) + case = {"id": cid, "doc": st0.key, "before": {"nodes": before, "ids": [], "rev": 0}, "correction": c} + try: + st1, rec = CO.apply(st0, c, store=SCHEMAS) + v1 = hashing.compute(st1.doc()) + case["expect"] = {"record": rec, "nodes": [dict(n, **v1[n["id"]]) for n in st1.nodes], "ids": st1.ids} + except Refusal as e: + case["expect"] = {"refusal": e.rule} + out.append(case) + return out + + +def resolve_vectors(hale): + src, names, states, final = hale["src"], hale["names"], hale["states"], hale["final"] + s0 = states[0] + d0 = s0.doc() + v0 = hashing.compute(d0) + out = [] + for cid, a in src["anchors_at_rev0"].items(): + nid = names.ids[a["node"]] + if a.get("container_of"): + nid = d0.nodes[nid]["parent"] + span = None + if "quote" in a: + t = hashing.plain(d0, nid) + i = t.index(a["quote"]) + span = [i, i + len(a["quote"])] + anchor = AN.make_anchor(d0, v0, nid, 0, span=span, store=STORE) + if "alias" in a: + anchor["node"] = a["alias"] + res = AN.resolve(final, anchor) + out.append({"id": cid, "package": "fixtures/packages/" + hale["key"], "anchor": anchor, "expect": res}) + return out + + +def rights_vectors(hale): + out = OUT + w = hale["witness"] + stages = json.load(open(os.path.join(ROOT, "registry", "stages", "scienting-stages-default.json")))["stages"] + policy = json.load(open(os.path.join(out, "fixtures", "records", "policy.json"))) + cases = [] + for cid, stage, proc, now, pols in [ + ("convert-local", "convert-model", "local", "2026-10-11T00:00:00Z", []), + ("convert-outside", "convert-model", "outside", "2026-10-11T00:00:00Z", []), + ("review-tenancy-unknown", "review-model", "tenancy", "2026-10-11T00:00:00Z", []), + ("review-tenancy-policy", "review-model", "tenancy", "2026-10-11T00:00:00Z", [policy]), + ("index", "index", "local", "2026-10-11T00:00:00Z", []), + ("embed-outside-refused", "embed", "outside-no-retention", "2026-10-11T00:00:00Z", [policy]), + ("publish-quotes", "publish-quotes", "local", "2026-10-11T00:00:00Z", []), + ("read-expired", "read", "local", "2027-09-01T00:00:00Z", []), + ("accessible-copy-unknown", "accessible-copy", "local", "2026-10-11T00:00:00Z", []), + ]: + uses, expired = RI.effective(w, pols, now) + ok, lacking = RI.check(stages[stage], proc, uses) + cases.append({"id": cid, "rights": w["rights"], "origin": w["origin"], "witness_sha256": w["sha256"], + "policies": pols, "stage": stage, "requires": stages[stage], "processor": proc, "now": now, + "expect": {"allowed": ok, "lacking": lacking, "expired": expired}}) + oa = rights_record("open") + sub = w["rights"] + cases.append({"id": "combine", "rights": [oa, sub], + "expect": RI.combine([RI.flat(oa), RI.flat(sub)])}) + backends = [json.load(open(os.path.join(out, "fixtures", "records", "backend-%s.json" % b))) for b in ("docling", "examplevendor")] + profiles = [json.load(open(os.path.join(out, "fixtures", "records", "profile-%s.json" % p))) for p in ("smithlab", "acme")] + for b in backends: + for p in profiles: + ok, failed = RI.backend_allowed(b, p) + cases.append({"id": "backend-%s-%s" % (b["name"], p["team"]), "backend": b, "profile": p, + "expect": {"allowed": ok, "failed": failed}}) + return cases + + +# --- records ------------------------------------------------------------------------ + + +def wr(out, rel, rec): + path = os.path.join(out, "fixtures", "records", rel) + os.makedirs(os.path.dirname(path), exist_ok=True) + with open(path, "wb") as f: + f.write((jcs.dumps(rec) + "\n").encode() if not isinstance(rec, bytes) else rec) + + +CTX = ["http://www.w3.org/ns/anno.jsonld", "https://paperspec.scient.ing/context/scienting-1.jsonld"] + + +def ann_hash(a): + return H(jcs.dumpb({k: v for k, v in a.items() if k not in ("status", "receipt", "modified")})) + + +TAG = "tag:scient.ing,2026:" +# A model's provenance: enough to name the weights and the instructions it ran with (all illustrative). +MODEL = {"name": "example-model", "provider": "Example Models (illustrative)", "version": "2026-09", + "weights": sha256_hex("illustrative weights"), "prompt": sha256_hex("illustrative review prompt"), + "parameters": sha256_hex("illustrative sampling parameters"), "processor": "local"} + + +def records(out, hale): + names, final = hale["names"], hale["final"] + doc = final.doc() + vals = hashing.compute(doc) + rev = final.rev + I = names.ids + HALE = hale["key"] + QHALE = STORE + "/" + HALE + OKAFOR = Names.registry["okafor2025open"].key + DRAFT = Names.registry["smithlab2027charges"].key + + def anchor(name, quote=None): + nid = I[name] + span = None + if quote: + t = hashing.plain(doc, nid) + i = t.index(quote) + span = [i, i + len(quote)] + return AN.make_anchor(doc, vals, nid, rev, span=span, store=STORE) + + wr(out, "roster.json", ROSTER) + # The doubtful reading behind the first correction, as the converter raised it before anyone answered it. + sus = {"format": "scienting-suspect/1", "kind": "number", "node": I["@s4"], "a": "10-3", "b": "10\u22123", + "crop": crop_sha(I["@s4"]), + "note": "The text layer reads a hyphen on the line; the page image shows a raised minus three."} + sus = dict(sus, id=record_id(sha256_hex(jcs.dumpb(sus)))) + wr(out, "suspect.json", sus) + wr(out, "anchor-span.json", anchor("@s3", "first test case")) + wr(out, "anchor-cell.json", anchor("@cc_ak")) + wr(out, "anchor-paragraph.json", AN.make_anchor(doc, vals, doc.nodes[I["@s3"]]["parent"], rev, store=STORE)) + long_anchor = AN.make_anchor(doc, vals, I["@s2"], rev, store=STORE) + wr(out, "anchor-leaf.json", long_anchor) + # A public layer's anchor on a paywalled paper: keyed by the pages, no text. + fps = [p["page_fp"] for p, _ in hale["pages"]] + layer_id = TAG + "layer:smithlab/kp4m2x7q" + pk = crypto.page_key(fps, "layer:smithlab/kp4m2x7q") + hk = hashing.Hasher(pk) + ka = anchor("@cc_ak") + keyed_vals = hashing.compute(doc, hk) + ka = {"format": "scienting-anchor/1", "store": STORE, "doc": ka["doc"], "node": ka["node"], "kind": "cell", + "own_hash": keyed_vals[ka["node"]]["own_hash"], "node_hash": keyed_vals[ka["node"]]["node_hash"], + "quote": {"mac": hk(norm(ka["quote"]["exact"])), "length": len(ka["quote"]["exact"])}, + "context": {"table_label_mac": hk(norm(ka["context"]["table_label"])), + "row_path_mac": [hk(norm(x)) for x in ka["context"]["row_path"]], + "column_path_mac": [hk(norm(x)) for x in ka["context"]["column_path"]]}, + "rev": rev, "keyed": {"scheme": "hkdf-pages", "algorithm": "sha-256", "context": "layer:smithlab/kp4m2x7q", + "pages": [crypto.page_hash(f) for f in fps]}} + wr(out, "anchor-keyed.json", ka) + # Rights, policy, backends, profiles. + wr(out, "rights-open.json", rights_record("open")) + wr(out, "rights-subscription.json", rights_record("subscription")) + ccc = rights_record("subscription") + ccc.update({"license": {"text": "Annual collective license with internal AI re-use (fictional)."}, + "basis": "collective-license", "valid_until": "2027-06-30T23:59:59Z"}) + wr(out, "rights-collective.json", ccc) + policy = RC.seal({"format": "scienting-policy/1", "project": "smithlab-charges", + "applies_to": {"basis": ["subscription"], "doi_prefixes": ["10.5555/"]}, + "uses": {"ai": {"internal/tenancy": True}}, + "statement": "Our institutional agreement covers internal AI use in our own cloud account for " + "these papers (fictional).", + "by": "ana", "at": "2026-10-05T09:00:00Z", "valid_until": "2027-08-31T23:59:59Z"}, + secret("ana"), "ana") + wr(out, "policy.json", policy) + wr(out, "backend-docling.json", { + "format": "scienting-backend/1", "name": "docling", "version": "illustrative", "stage": "read", + "processor": "local", "code_license": {"spdx": "MIT"}, + "weights": [{"name": "layout model", "license": {"spdx": "Apache-2.0"}}], "conditions": []}) + wr(out, "backend-examplevendor.json", { + "format": "scienting-backend/1", "name": "examplevendor", "version": "1.0", "stage": "read", + "processor": "local", "code_license": {"spdx": "Apache-2.0"}, + "weights": [{"name": "example weights", "license": {"text": "A fictional weight license with conditions."}}], + "conditions": [{"id": "revenue-cap", "kind": "revenue-cap", "usd": 5000000}, + {"id": "no-competition", "kind": "no-competition", "vendor": "examplevendor"}, + {"id": "purpose", "kind": "purpose", "allowed": ["research", "personal", "education", "startup"]}]}) + wr(out, "profile-smithlab.json", {"format": "scienting-profile/1", "team": "smithlab", "purpose": "research", + "revenue_or_funding_usd": {"at_most": 2000000}, "competes_with": [], + "recorded_by": "ana", "at": "2026-10-01T00:00:00Z"}) + wr(out, "profile-acme.json", {"format": "scienting-profile/1", "team": "acme", "purpose": "commercial", + "revenue_or_funding_usd": {"at_most": None}, "competes_with": None, + "recorded_by": "acme-admin", "at": "2026-10-01T00:00:00Z"}) + # A layer with one annotation of each common kind. + creator = {"id": TAG + "key:ana", "type": "Person", "name": "Ana Example"} + model = {"id": TAG + "software:example-model", "type": "Software", "name": "A model (illustrative)"} + + def target(a): + return {"type": "SpecificResource", "source": TAG + "doc:" + QHALE, + "selector": [{"type": "AnchorSelector", "anchor": a}] + + ([{"type": "TextQuoteSelector", "exact": a["quote"]["exact"], + "prefix": a["quote"].get("prefix", ""), "suffix": a["quote"].get("suffix", "")}] + if "quote" in a and "exact" in a["quote"] else [])} + + def ann(body, tgt, motivation, status="proposed", who=creator, created="2026-10-11T19:00:00Z"): + a = {"@context": CTX, "type": "Annotation", "layer": layer_id, "motivation": motivation, "creator": who, + "created": created, "body": body, "target": tgt} + a["id"] = TAG + "annotation:smithlab/" + record_id(H(jcs.dumpb(a))) + a["status"] = status + return a + + ex_body = {"format": "scienting-exercise/1", "exercise": "anchor", + "prompt": "Find the table cell that gives the Set A bond constant for the CT–CT bond.", + "key": {"elements": [{"anchors": [anchor("@cc_ak")], "points": "1", + "feedback": {"hit": "That is the cell.", "miss": "Look in Table 1, row CT–CT."}}]}, + "rule": {"match": "same-node"}} + check_body = {"format": "scienting-exercise/1", "exercise": "check", + "prompt": "Does the cited passage support the claim that harmonic terms are the most common choice?", + "key": {"verdict": {"value": "supports", "points": "1"}, + "elements": [{"anchors": [anchor("@s1", "the most common description")], "points": "1"}]}, + "rule": {"match": "overlap", "min_overlap": "0.5"}} + anns = [ + ann({"type": "TextualBody", "kind": "gloss", "audience": "novice", "format": "text/markdown", "language": "en", + "value": "A *harmonic* term treats a bond like a spring: the energy grows with the square of the stretch."}, + target(anchor("@s2", "bond force constant")), "describing", "confirmed"), + ann({"type": "SpecificResource", "kind": "claim-link", "source": "lode:amber/k-bond", "pin": "illustrative-pin", + "role": "states"}, target(anchor("@s2")), "linking", "confirmed"), + ann({"type": "TextualBody", "kind": "comment", "value": "The step size matters more than the text admits."}, + target(anchor("@s6a", "steps of 0.01")), "commenting"), + ann({"type": "TextualBody", "kind": "question", "for": "group", + "value": "Why fit to a scan first and to frequencies second?"}, + target(AN.make_anchor(doc, vals, I["@sec2"], rev, store=STORE)), "questioning"), + ann({"type": "TextualBody", "kind": "citation-context", "reference": I["@r2"], "verdict": "cannot-tell", + "reason": "value", "value": "Cited for the band position; the reference is not in the library."}, + target(anchor("@s3", "1595")), "assessing"), + ann({"type": "TextualBody", "kind": "generated", "value": "Two panels: an energy scan and its fit residual.", + "generator": {"model": MODEL, "run": "illustrative-run-1"}}, + target(AN.make_anchor(doc, vals, I["@fig1"], rev, store=STORE)), "describing", "proposed", model), + ann({"type": "TextualBody", "kind": "exercise", "value": ex_body["prompt"], "exercise": ex_body}, + target(AN.make_anchor(doc, vals, I["@tab1"], rev, store=STORE)), "assessing", "confirmed"), + ann({"type": "TextualBody", "kind": "exercise", "value": check_body["prompt"], "exercise": check_body}, + target(anchor("@s1")), "assessing", "confirmed"), + # A person's description of the figure, which an accessible export may use because it is confirmed. + ann({"type": "TextualBody", "kind": "description", "role": "alt", "language": "en", + "value": "Energy along the C–C bond stretch (panel a) and the fit residual (panel b)."}, + target(AN.make_anchor(doc, vals, I["@fig1"], rev, store=STORE)), "describing", "confirmed"), + ] + anns.append(ann({"type": "TextualBody", "kind": "comment", "value": "Agreed; see the residual panel."}, + {"type": "SpecificResource", "source": anns[2]["id"]}, "replying", created="2026-10-11T19:05:00Z")) + confirmed = [a for a in anns if a["status"] == "confirmed"] + lr = RC.seal({"format": "scienting-receipt/1", "doc": HALE, "rev": rev, "level": "F3", + "scope": "targeted:layer", "nodes": [], + "records": sorted([["annotation", a["id"].rsplit("/", 1)[1], ann_hash(a)] for a in confirmed]), + "evidence": [], "by": "ana", "at": "2026-10-11T19:30:00Z"}, secret("ana"), "ana") + for a in confirmed: + a["receipt"] = lr["id"] + wr(out, "layer/layer.json", {"@context": CTX, "format": "scienting-layer/1", "id": layer_id, + "type": "AnnotationCollection", "label": "Smith lab reading of Hale and Osei", + "purpose": "Glosses, claim links and exercises for new students.", + "audience": "student", "visibility": "team", "license": {"spdx": "CC-BY-4.0"}, + "creator": creator, "created": "2026-10-11T19:00:00Z", "project": "smithlab-charges", + "docs": [QHALE], "total": len(anns)}) + wr(out, "layer/annotations.jsonl", jsonl(anns)) + wr(out, "layer/receipt.json", lr) + # Submissions and grades. + ex_ann = anns[6] + sub_ok = {"format": "scienting-submission/1", "exercise": ex_ann["id"], "doc": QHALE, + "rev": rev, "student": "s-7k2m", "answers": {"anchors": [anchor("@cc_ak")]}, + "submitted_at": "2026-10-20T10:00:00Z"} + sub_ok["id"] = record_id(H(jcs.dumpb(sub_ok))) + sub_miss = dict(sub_ok, student="s-9q4p", answers={"anchors": [anchor("@cc_bk")]}) + sub_miss.pop("id") + sub_miss["id"] = record_id(H(jcs.dumpb(sub_miss))) + ch_ann = anns[7] + sub_check = {"format": "scienting-submission/1", "exercise": ch_ann["id"], "doc": QHALE, + "rev": rev, "student": "s-7k2m", + "answers": {"verdict": "supports", "anchors": [anchor("@s1", "most common description of covalent")]}, + "submitted_at": "2026-10-20T10:05:00Z"} + sub_check["id"] = record_id(H(jcs.dumpb(sub_check))) + grades = [] + for name, sub, body in (("anchor-hit", sub_ok, ex_body), ("anchor-miss", sub_miss, ex_body), + ("check-overlap", sub_check, check_body)): + g = GR.grade(body, sub, final) + wr(out, "submissions/%s.json" % name, sub) + wr(out, "grades/%s.json" % name, g) + grades.append({"id": name, "package": "fixtures/packages/" + hale["key"], "exercise": body, + "submission": sub, "expect": g}) + wv(out, "grading.jsonl", grades) + # Project. + wr(out, "project.json", { + "format": "scienting-project/1", "key": "smithlab-charges", "store": STORE, "name": "Charges and bonds", + "members": [{"person": "Ana Example", "role": "owner", "keys": ["ana"]}, + {"person": "Ben Example", "role": "editor", "keys": ["ben", "ben-spot"]}, + {"person": "Cara Example", "role": "reader", "keys": ["cara"]}], + "documents": [{"doc": QHALE, "reason": "The bond constants we start from.", + "tags": ["parameters"], "status": {"Ben Example": "read", "Cara Example": "reading"}}, + {"doc": OKAFOR, "reason": "Solvent shifts for the validation set.", "tags": ["spectra"]}], + "paths": [{"id": "onboarding", "title": "First week", "steps": [ + {"type": "document", "ref": QHALE, "note": "Read the introduction."}, + {"type": "node", "ref": QHALE + "#" + I["@tab1"], "note": "Then the table."}, + {"type": "claim", "ref": "lode:amber/k-bond"}]}], + "layers": [layer_id], "datasets": ["ds-hale-bond-params", "ds-hale-ctct-scan"], "views": ["ctct-scan"], + "drafts": [STORE + "/" + DRAFT], "claims": {"lode": "amber"}, + "settings": {"digit_rule": "anchored-sections", "drift_threshold": "0.25", + "spot_check": {"rate": "0.05", "minimum": 10}, "rights_unknown": "refuse", + "stages": "scienting-stages-default", + "log": {"origin": "scient.ing/log/smithlab", "witnesses": ["wit"], "threshold": 1}}}) + # A digitization of panel a, and the dataset it yields. + p2 = hale["pages"][1][0] + pa = I["@pa"] + ft = {t["text"]: t["id"] for t in doc.nodes[pa]["attrs"]["figure_text"]} + pts = [((110.0, 360.0), ("1.45", "3.10")), ((150.0, 330.0), ("1.50", "0.40")), ((190.0, 300.0), ("1.55", "2.80"))] + dg = {"format": "scienting-digitization/1", "doc": QHALE, + "target": {"anchor": AN.make_anchor(doc, vals, pa, rev, store=STORE), "page_fp": p2["page_fp"], + "region": [72.0, 260.0, 300.0, 410.0], "witness": hale["witness"]["sha256"]}, + "axes": [{"id": "x", "scale": "linear", "unit": "angstrom", + "calibration": [{"at": [90.0, 400.0], "value": "1.4"}, {"at": [210.0, 400.0], "value": "1.6"}], + "check": {"at": [150.0, 400.0], "value": "1.5"}, "label": {"panel": pa, "figure_text": ft["r (Å)"]}}, + {"id": "y", "scale": "linear", "unit": "kcal / mol", + "calibration": [{"at": [80.0, 400.0], "value": "0"}, {"at": [80.0, 280.0], "value": "4"}], + "label": {"panel": pa, "figure_text": ft["E (kcal mol⁻¹)"]}}], + "series": [{"id": "scan", "legend": "scan", "mark": {"color": "#285aa0", "marker": "circle"}, "kind": "points", + "values": [{"at": list(at), "value": {"x": x, "y": y}, + "uncertainty": {"x": "0.01", "y": "0.05", "resolution": "0.01", "marker": "0.02", + "calibration": "0.01"}} for at, (x, y) in pts]}], + "method": {"kind": "manual", "tool": {"name": "hand", "version": "0"}}, + "verification": {"image": "", "residual": "0.4", "max_residual": "0.9"}, + "confirmation": None, "dataset": "ds-hale-ctct-scan", "rev": rev} + dg["verification"]["image"] = crop_sha("overlay of panel a") + dg["id"] = record_id(H(jcs.dumpb(dg))) + wr(out, "digitization.json", dg) + body = {k: v for k, v in dg.items() if k != "confirmation"} + conf = RC.seal({"format": "scienting-receipt/1", "doc": HALE, "rev": rev, "level": "F3", + "scope": "targeted:digitization", "nodes": [], + "records": [["digitization", dg["id"], H(jcs.dumpb(body))]], + "evidence": [{"kind": "crop", "node": pa, "sha256": crop_sha("overlay of panel a")}], + "by": "ana", "at": "2026-10-11T20:00:00Z"}, secret("ana"), "ana") + wr(out, "digitization-confirmation.json", conf) + ds = {"format": "scienting-dataset/1", "id": "ds-hale-ctct-scan", "name": "hale-ctct-scan", + "title": "Energy along the C–C stretch, read from Figure 1a", + "resources": [{"name": "scan", "path": "data.csv", "format": "csv", "encoding": "utf-8", + "schema": {"fields": [{"name": "point", "type": "string"}, + {"name": "r", "type": "number", "unit": "angstrom", + "uncertainty": {"field": "r_u", "kind": "resolution"}}, + {"name": "r_u", "type": "number", "unit": "angstrom"}, + {"name": "e", "type": "number", "unit": "kcal / mol", + "uncertainty": {"field": "e_u", "kind": "resolution"}}, + {"name": "e_u", "type": "number", "unit": "kcal / mol"}], + "primaryKey": "point"}, + "origin": {"kind": "digitized", "digitization": dg["id"], "anchors": "anchors.jsonl"}}]} + csvd = "point,r,r_u,e,e_u\n" + "".join("p%d,%s,0.01,%s,0.05\n" % (i, x, y) for i, (_, (x, y)) in enumerate(pts)) + va = [{"resource": "scan", "row": "p%d" % i, "field": f, "digitization": dg["id"], "series": "scan", "point": i} + for i in range(len(pts)) for f in ("r", "e")] + wr(out, "datasets/ds-hale-ctct-scan/datapackage.json", ds) + wr(out, "datasets/ds-hale-ctct-scan/data.csv", csvd.encode()) + wr(out, "datasets/ds-hale-ctct-scan/anchors.jsonl", jsonl(va)) + ds_files = sorted([["anchors.jsonl", H(jsonl(va)), len(jsonl(va))], ["data.csv", H(csvd), len(csvd.encode())], + ["datapackage.json", H(jcs.dumps(ds) + "\n"), len((jcs.dumps(ds) + "\n").encode())]]) + ds_hash = H(jcs.dumpb({"format": "scienting-dataset/1", "files": ds_files})) + wr(out, "view.vl.json", { + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "usermeta": {"scienting": {"format": "scienting-view/1", "id": "ctct-scan", + "data": [{"name": "ds-hale-ctct-scan", "dataset": "ds-hale-ctct-scan", + "hash": ds_hash, "resource": "scan"}]}}, + "data": {"name": "ds-hale-ctct-scan"}, "mark": {"type": "point"}, + "encoding": {"x": {"field": "r", "type": "quantitative", "title": "r (Å)"}, + "y": {"field": "e", "type": "quantitative", "title": "E (kcal/mol)"}}}) + # QA report. + q1 = hale["by_name"]["q1"] + q2 = hale["by_name"]["q2"] + n = len(q1["qa"]["sample"]) + len(q2["qa"]["sample"]) + k = len(q1["qa"]["errors"]) + len(q2["qa"]["errors"]) + wr(out, "qa-report.json", RC.seal({ + "format": "scienting-qa-report/1", "delivery": "smithlab evidence pilot (fictional)", + "docs": [QHALE], "receipts": [hale["by_name"]["r1"]["id"], hale["by_name"]["r4"]["id"]], + "reviewers": [{"key": "ana", "sampled": n, "errors": k, "confidence": "0.95", "method": "clopper-pearson", + "bound": RC.bound_string(k, n)}], + "by": "ana", "at": "2026-10-12T10:00:00Z"}, secret("ana"), "ana")) + # A checklist for an accessible HTML export of the paper, and the receipt that covers it (spec/08 §8.11). + html_sha = H("accessible HTML export of %s (synthetic)" % HALE) + checker = {"name": "example-checker", "version": "1.0"} + checklist = {"format": "scienting-checklist/1", "doc": QHALE, "rev": rev, + "standard": {"name": "WCAG 2.1", "level": "AA", "url": "https://www.w3.org/TR/WCAG21/"}, + "export": {"kind": "html", "sha256": html_sha, "size": 48213}, + "items": [ + {"criterion": "1.1.1", "result": "pass", "method": "manual", + "note": "Every figure has a confirmed description in the layer."}, + {"criterion": "1.2.1", "result": "not-applicable", "method": "manual", "note": "No audio or video."}, + {"criterion": "1.3.1", "result": "pass", "method": "manual", + "note": "Headings, lists and table headers are marked up; each cell names its header path."}, + {"criterion": "1.3.2", "result": "pass", "method": "automated", "tool": checker}, + {"criterion": "1.4.3", "result": "pass", "method": "automated", "tool": checker}, + {"criterion": "1.4.5", "result": "pass", "method": "manual", + "note": "Equations are MathML, never images of text."}, + {"criterion": "2.4.2", "result": "pass", "method": "automated", "tool": checker}, + {"criterion": "3.1.1", "result": "pass", "method": "automated", "tool": checker}], + "by": "ana", "at": "2026-10-12T11:00:00Z"} + checklist_hash = H(jcs.dumpb(checklist)) + checklist["id"] = record_id(checklist_hash) + wr(out, "checklist/checklist.json", checklist) + wr(out, "checklist/receipt.json", RC.seal({ + "format": "scienting-receipt/1", "doc": HALE, "rev": rev, "level": "F3", + "scope": "targeted:checklist", "nodes": [], "records": [["checklist", checklist["id"], checklist_hash]], + "evidence": [{"kind": "source-file", "sha256": html_sha, "note": "The exported HTML."}], + "by": "ana", "at": "2026-10-12T11:30:00Z"}, secret("ana"), "ana")) + # The target set of targeted F3 (spec/08 §8.10) under each digit rule: the dataset's cells, the sentence a + # confirmed claim link anchors, and the panel a digitization reads from are the anchored nodes. + dataset_anchors = [json.loads(x) for x in + hale["files"]["datasets/ds-hale-bond-params/anchors.jsonl"].decode().splitlines()] + anchored = sorted({a["anchor"]["node"] for a in dataset_anchors} | {I["@s2"], pa}) + wv(out, "targets.jsonl", [{"id": "hale-" + rule, "package": "fixtures/packages/" + hale["key"], + "anchored": anchored, "digit_rule": rule, + "expect": {"nodes": TG.target_set(doc, anchored, rule)}} + for rule in TG.DIGIT_RULES]) + # Proofs (spec/08 §8.5, spec/11 §11.5): one node of the first receipt was covered, and revision 12 extends + # revision 8 of the correction history. + r1 = hale["by_name"]["r1"] + items = crypto.receipt_items(r1) + wr(out, "proof-inclusion.json", {"format": "scienting-proof/1", "kind": "inclusion", "receipt": r1["id"], + "item": items[3], "index": 3, "size": len(items), "root": r1["root"], + "path": crypto.inclusion_path(items, 3)}) + hist = history_items(hale["records"]) + wr(out, "proof-consistency.json", {"format": "scienting-proof/1", "kind": "consistency", "doc": QHALE, + "from_rev": 8, "to_rev": len(hist), "from_root": crypto.history_root(hist[:8]), + "to_root": hale["document"]["history"], "path": crypto.consistency_proof(hist, 8)}) + # A checkpoint of the team's log (spec/23), as the parsed form of its signed note. + entries = [LG.entry(r) for r in hale["receipts"]] + [LG.entry(ROSTER)] + signers = [("ana", secret("ana")), ("wit", secret("wit"))] + note = LG.write_log(entries, "scient.ing/log/smithlab", signers, os.path.join(out, "fixtures", "records", "log")) + parsed = LG.parse_checkpoint(note) + wr(out, "checkpoint.json", {"format": LG.FORMAT, "origin": parsed["origin"], "size": parsed["size"], + "root": parsed["root"], "note": note, + "signatures": [{"name": n, "key_hash": kh.hex(), "value": base64.b64encode(sig).decode()} + for n, kh, sig in parsed["signatures"]]}) + # A receipt signed with ML-DSA-65 (FIPS 204) by dana: two sentences read against the page, at F2. + two = sorted([I["@s1"], I["@s2"]]) + wr(out, "receipt-ml-dsa.json", seal({"format": "scienting-receipt/1", "doc": HALE, "rev": rev, "level": "F2", + "scope": "targeted:ml-dsa", "nodes": [[n, vals[n]["node_hash"]] for n in two], + "evidence": [{"kind": "person", "by": "dana"}], "by": "dana", + "at": "2026-10-13T09:00:00Z"}, "dana")) + # Draft snapshot and sentence IDs. + s5 = I["@s5"] + snap_anchor = AN.make_anchor(doc, vals, s5, rev, store=STORE) + wr(out, "snapshot.json", {"format": "scienting-snapshot/1", "store": STORE, "made_at": "2026-10-11T21:00:00Z", + "quotes": [{"address": AN.format_address(STORE, HALE, s5, vals[s5]["node_hash"]), + "anchor": snap_anchor, "text": norm(hashing.plain(doc, s5)), + "fidelity": "F3", "result": "current"}], + "claims": [{"ref": "amber/k-bond", "pin": "illustrative-pin", "level": "illustrative", + "typst": "K_r"}], + "datasets": [{"id": "ds-hale-ctct-scan", "hash": ds_hash}]}) + draft = Names.registry["smithlab2027charges"] + dd = Doc(DRAFT, [json.loads(x) for x in open(os.path.join(out, "fixtures", "packages", DRAFT, "nodes.jsonl"))]) + lines = [] + for nid in dd.preorder(): + if dd.nodes[nid]["kind"] == "sentence": + sec = next((a for a in reversed(dd.ancestors(nid)) if dd.nodes[a]["kind"] == "section"), None) + lines.append({"id": nid, "text_hash": dd.nodes[nid]["text_hash"], "section": sec, + "ord": dd.nodes[nid]["ord"]}) + lines[-1]["pinned"] = "energy-sentence" + wr(out, "draft-ids.jsonl", jsonl(lines)) + + +# --- invalid packages --------------------------------------------------------------- + + +def invalid(out, tiny): + base = os.path.join(out, "fixtures", "invalid") + files = tiny["files"] + nodes = [json.loads(x) for x in files["nodes.jsonl"].decode().splitlines()] + nm = tiny["names"].ids + + def edit_nodes(fn): + ns = copy.deepcopy(nodes) + fn(ns) + return jsonl(ns) + + def by(ns, name): + return next(n for n in ns if n["id"] == nm[name]) + + def case(name, rule, change, note, raw=None): + f = dict(files) + f.update(change) + d = os.path.join(base, name, "package") + write(d, f) + if raw: + raw(d) + with open(os.path.join(base, name, "expect.json"), "wb") as fh: + fh.write((jcs.dumps({"rule": rule, "note": note}) + "\n").encode()) + + case("hash-mismatch", "doc.hash.node-hash", {"nodes.jsonl": edit_nodes(lambda ns: by(ns, "@a").update(node_hash="0" * 64))}, + "A node_hash that does not recompute.") + case("text-edited", "doc.hash.text-hash", {"nodes.jsonl": edit_nodes( + lambda ns: by(ns, "@a").update(content=[{"kind": "text", "text": "The value is 42.5 at 300 K."}]))}, + "Text changed without its hashes.") + case("unknown-kind", "package.schema", {"nodes.jsonl": edit_nodes(lambda ns: by(ns, "@p2").update(kind="aside"))}, + "Kinds outside the list are refused.") + case("heading-not-first", "doc.tree.child", {"nodes.jsonl": edit_nodes(lambda ns: _swap_first(ns, nm["@sec"]))}, + "A heading must be a section's first child.") + case("cite-not-reference", "doc.run.cite", {"nodes.jsonl": edit_nodes( + lambda ns: by(ns, "@b").update(content=[r if r["kind"] != "cite" else dict(r, refs=[nm["@a"]]) + for r in by(ns, "@b")["content"]]))}, + "A cite run names a node that is not a reference.") + case("unlisted-file", "package.manifest.unlisted", {}, "A file the manifest does not list.", + raw=lambda d: open(os.path.join(d, "notes.txt"), "w").write("stray\n")) + case("manifest-hash", "package.manifest.hash", {}, "A file changed after the manifest was written.", + raw=lambda d: open(os.path.join(d, "provenance.json"), "a").write(" ")) + case("not-canonical", "package.file.canonical", {}, "A line that is valid JSON but not canonical JSON.", + raw=lambda d: _rewrite_noncanonical(d)) + case("root-mismatch", "doc.hash.root", {"document.json": _doc_edit(files, root="1" * 64)}, + "document.json's root is not the root node's node_hash.") + case("receipt-root", "doc.receipt.root", {"receipts.jsonl": _receipt_edit(files, root="2" * 64)}, + "A receipt whose Merkle root does not recompute.") + case("receipt-signature", "doc.receipt.signature", {"receipts.jsonl": _receipt_edit(files, at="2026-10-11T12:00:01Z")}, + "A receipt changed after it was signed.") + case("checks-only-plain", "doc.policy.withheld", {"document.json": _doc_edit(files, policy="checks-only")}, + "A checks-only package that still carries text and plain hashes.") + case("bad-id", "package.schema", {"nodes.jsonl": edit_nodes(lambda ns: _rename(ns, nm["@d"], "i1lo0uu"))}, + "IDs use Crockford base32, which has no i, l, o or u.") + case("empty-optional-file", "package.file.empty", {"suspects.jsonl": b""}, "An optional JSONL file with no records.") + case("alias-dangling", "doc.id.successor", {"ids.jsonl": jsonl([{"id": "b-p01-text-001", "kind": "alias", + "successor": "zzzzzzz"}])}, + "An alias whose node does not exist.") + case("location-unknown-page", "doc.location.page", {"locations.jsonl": jsonl([ + {"node": nm["@a"], "page_fp": "3" * 64, "page": 1, "boxes": [[72, 72, 200, 84]]}])}, + "A location on a page no witness has.") + case("style-sup-sub", "doc.run.style", {"nodes.jsonl": edit_nodes(lambda ns: by(ns, "@c").update( + content=[{"kind": "text", "text": "A second paragraph.", "style": ["sub", "sup"]}]))}, + "A run cannot be both a subscript and a superscript.") + # Zipped packages that break spec/12 §12.2: the tiny package's files plus one bad entry. + tiny_dir = os.path.join(out, "fixtures", "packages", tiny["key"]) + entries = [] + for rel in sorted(os.path.relpath(os.path.join(d, f), tiny_dir).replace(os.sep, "/") + for d, _, fs in os.walk(tiny_dir) for f in fs): + with open(os.path.join(tiny_dir, rel), "rb") as fh: + entries.append((tiny["key"] + "/" + rel, fh.read(), 0o644)) + + def zip_case(name, rule, note, extra): + d = os.path.join(base, name) + os.makedirs(d) + with zipfile.ZipFile(os.path.join(d, "package" + ZIP_EXTENSION), "w") as zf: + for ename, data, mode in entries + extra: + zi = zipfile.ZipInfo(ename, date_time=(1980, 1, 1, 0, 0, 0)) + zi.compress_type = zipfile.ZIP_STORED + zi.create_system = 3 + zi.external_attr = mode << 16 + zf.writestr(zi, data) + with open(os.path.join(d, "expect.json"), "wb") as fh: + fh.write((jcs.dumps({"rule": rule, "note": note}) + "\n").encode()) + + zip_case("zip-traversal", "package.zip.entry", "An archive entry whose path leaves the package folder.", + [(tiny["key"] + "/../escape.txt", b"outside\n", 0o644)]) + zip_case("zip-symlink", "package.zip.entry", "An archive entry that is a symbolic link.", + [(tiny["key"] + "/assets/link", b"document.json", 0o120777)]) + # Rules the audit found no broken package for. + case("missing-required-file", "package.file.required", {"provenance.json": None}, "A required file is missing.") + case("counts-wrong", "doc.counts", {"document.json": _doc_edit(files, counts={"nodes": 1, "leaves": 1})}, + "document.json's counts are not the number of nodes and leaves.") + case("rev-without-corrections", "doc.correction.rev", {"document.json": _doc_edit(files, rev=3)}, + "document.json's rev is not the number of corrections.") + case("receipt-unsorted-nodes", "doc.receipt.nodes", {"receipts.jsonl": _receipt_edit( + files, nodes=list(reversed([json.loads(x) for x in files["receipts.jsonl"].decode().splitlines()][0]["nodes"])))}, + "A receipt whose nodes are not sorted by ID.") + case("retired-live", "doc.id.retired-live", {"ids.jsonl": jsonl([ + {"id": nm["@a"], "kind": "retired", "successor": None, "node_kind": "sentence", "rev": 1}])}, + "An ID that is both live and retired.") + case("manifest-key", "package.manifest.key", {}, "The manifest names another key than document.json.", + raw=lambda d: _manifest_edit(d, key="other2026example-0000")) + case("unsafe-path", "package.path.unsafe", {}, "The manifest lists a path that leaves the package.", + raw=lambda d: _manifest_edit(d, files=[{"path": "../escape.txt", "sha256": "0" * 64, "size": 1}] + + json.load(open(os.path.join(d, "MANIFEST.json")))["files"])) + case("crlf", "package.file.canonical", {}, "A file whose lines end in CR LF, which is not the canonical form.", + raw=lambda d: _crlf(d)) + signer = [json.loads(x) for x in files["receipts.jsonl"].decode().splitlines()][0] + case("signer-mismatch", "doc.receipt.signature", {"receipts.jsonl": jsonl([ + RC.seal(dict(signer, by="cara"), secret("ana"), "ana")])}, + "A receipt whose signature was made with another key than the signer it names.") + case("history-wrong", "doc.history", {"document.json": _doc_edit(files, history="4" * 64)}, + "document.json's history is not the root over the corrections.") + d0 = json.loads(files["document.json"]) + wk = d0["work"]["key"] + bad = wk[:-4] + "zzzz" + case("key-suffix", "doc.key.suffix", {"document.json": _doc_edit(files, key=bad, work=dict(d0["work"], key=bad))}, + "A work key whose hash part is not the hash of the work's DOI.") + case("key-work", "doc.key.work", {"document.json": _doc_edit(files, key=wk + ".si")}, + "A document key whose suffix is not the version's.") + + +def _manifest_edit(d, **kw): + p = os.path.join(d, "MANIFEST.json") + m = json.load(open(p, encoding="utf-8")) + m.update(kw) + open(p, "w", encoding="utf-8").write(jcs.dumps(m) + "\n") + + +def _crlf(d): + p = os.path.join(d, "provenance.json") + data = open(p, "rb").read().replace(b"\n", b"\r\n") + open(p, "wb").write(data) + m = json.load(open(os.path.join(d, "MANIFEST.json"), encoding="utf-8")) + for f in m["files"]: + if f["path"] == "provenance.json": + f["sha256"], f["size"] = H(data), len(data) + open(os.path.join(d, "MANIFEST.json"), "w", encoding="utf-8").write(jcs.dumps(m) + "\n") + + +def _swap_first(ns, sec): + kids = sorted([n for n in ns if n["parent"] == sec], key=lambda n: n["ord"]) + kids[0]["ord"], kids[1]["ord"] = kids[1]["ord"], kids[0]["ord"] + d = Doc("x", ns) + order = d.preorder() + ns.sort(key=lambda n: order.index(n["id"])) + + +def _rename(ns, old, new): + for n in ns: + if n["id"] == old: + n["id"] = new + + +def _doc_edit(files, **kw): + d = json.loads(files["document.json"]) + d.update(kw) + return (jcs.dumps(d) + "\n").encode() + + +def _receipt_edit(files, **kw): + rs = [json.loads(x) for x in files["receipts.jsonl"].decode().splitlines()] + rs[0].update(kw) + return jsonl(rs) + + +def _rewrite_noncanonical(d): + p = os.path.join(d, "nodes.jsonl") + lines = open(p).read().splitlines() + lines[0] = json.dumps(json.loads(lines[0]), indent=None, separators=(", ", ": ")) + data = ("\n".join(lines) + "\n").encode() + open(p, "wb").write(data) + m = json.load(open(os.path.join(d, "MANIFEST.json"))) + for f in m["files"]: + if f["path"] == "nodes.jsonl": + f["sha256"], f["size"] = H(data), len(data) + open(os.path.join(d, "MANIFEST.json"), "w").write(jcs.dumps(m) + "\n") + + +# --- main ----------------------------------------------------------------------------- + + +OUT = ROOT + + +def main(out): + global OUT + OUT = out + for sub in ("fixtures/packages", "fixtures/records", "fixtures/invalid", "fixtures/keys"): + p = os.path.join(out, sub) + if os.path.exists(p): + shutil.rmtree(p) + os.makedirs(p) + vec = os.path.join(out, "vectors") + os.makedirs(vec, exist_ok=True) + for f in os.listdir(vec): + if f.endswith(".jsonl"): + os.remove(os.path.join(vec, f)) + for kid in KEYS: + with open(os.path.join(out, "fixtures", "keys", kid + ".ed25519.hex"), "w") as f: + f.write(secret(kid).hex() + "\n") + with open(os.path.join(out, "fixtures", "keys", "smithlab-team-secret.hex"), "w") as f: + f.write(TEAM_SECRET.hex() + "\n") + Names.registry.clear() + hale = build_hale(out) + build_checks_only(out, hale) + build_simple(out, "okafor2025open") + build_simple(out, "smithlab2027charges") + tiny = tiny_package(None) + tiny_dir = os.path.join(out, "fixtures", "packages", tiny["key"]) + write(tiny_dir, tiny["files"]) + # The same package zipped as spec/12 §12.2 says a producer writes a byte-identical archive. + write_zip(tiny_dir, tiny_dir + ZIP_EXTENSION) + records(out, hale) + vectors(out, hale, tiny) + invalid(out, tiny) + + +def cli(): + import argparse + ap = argparse.ArgumentParser( + description="Build every fixture and test vector from fixtures/src and the oracle. The build is " + "deterministic, and tools/check.py rebuilds into a temporary folder to prove it.") + ap.add_argument("--out", metavar="DIR", default=ROOT, + help="build into DIR instead of rewriting fixtures/ and vectors/ in this repository") + out = os.path.abspath(ap.parse_args().out) + if out != ROOT: + for sub in ("registry", "fixtures/src"): + dst = os.path.join(out, sub) + if not os.path.exists(dst): + shutil.copytree(os.path.join(ROOT, sub), dst) + main(out) + + +if __name__ == "__main__": + cli() diff --git a/tools/check.py b/tools/check.py new file mode 100644 index 0000000..d43a72e --- /dev/null +++ b/tools/check.py @@ -0,0 +1,1206 @@ +#!/usr/bin/env python3 +"""Check the whole repository. Exit status 0 means every check passed. + +Non-normative tooling; it needs Python 3.14 and the packages pixi installs (`jsonschema`, `cryptography`). +Usage: python3 tools/check.py [--quick] (--quick skips the determinism rebuild) +""" + +import base64 +import filecmp +import json +import os +import re +import sqlite3 +import subprocess +import sys +import shutil +import tempfile +import zipfile +from fractions import Fraction + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, ROOT) + +from tools.oracle import align as AL # noqa: E402 +from tools.oracle import anchors as AN # noqa: E402 +from tools.oracle import corrections as CO # noqa: E402 +from tools.oracle import crypto, db, fingerprint as FP, grade as GR, hashing, jcs, receipts as RC, rights as RI # noqa: E402 +from tools.oracle import package as PK # noqa: E402 +from tools.oracle import keys as K, log as LG, mldsa, targets as TG, vrf # noqa: E402 +import unicodedata # noqa: E402 +from tools.oracle.model import Doc # noqa: E402 +from tools.oracle.notation import fold_math # noqa: E402 +from tools.oracle.schema import Store, validate as sv # noqa: E402 +from jsonschema import Draft202012Validator # noqa: E402 +from jsonschema.exceptions import SchemaError # noqa: E402 +from tools.oracle.text import cp_to_utf16, letter_first, mint_node_id, norm, record_id, sha256_hex # noqa: E402 +from tools.oracle.tree import Refusal # noqa: E402 + +FAILS = [] +# Folders that are not part of the repository: version control, environments and caches. +SKIP_DIRS = {".git", ".pixi", "node_modules", "__pycache__", "_site", ".claude"} +COUNTS = {} + + +def ok(section, cond, msg): + COUNTS[section] = COUNTS.get(section, 0) + 1 + if not cond: + FAILS.append("%s: %s" % (section, msg)) + + +def p(*parts): + return os.path.join(ROOT, *parts) + + +def jl(path): + with open(path, encoding="utf-8") as f: + return [json.loads(x) for x in f] + + +def js(path): + with open(path, encoding="utf-8") as f: + return json.load(f) + + +STORE = Store(p("schemas")) + + +def fixture_key(stem): + """The key the rule of spec/02 §2.4 mints for a fixture source, which names its package folder.""" + if stem == "tiny2026example": + from tools.build import TINY + d = TINY["document"] + else: + d = js(p("fixtures", "src", stem + ".json"))["document"] + return K.document_key(K.work_key(d["work"].get("same_as"), d["meta"]), d["version"]) + + +HALE = fixture_key("hale2026harmonic") +TINY_KEY = fixture_key("tiny2026example") +SCHEMA_FILES = sorted(f for f in os.listdir(p("schemas")) if f.endswith(".schema.json")) +FORMAT_SCHEMA = {f["format"]: f["schema"] for f in js(p("registry", "formats.json"))["formats"]} + + +def schema_errors(name, rec): + return sv(STORE, name, rec) + + +def check_schemas(): + for f in SCHEMA_FILES: + s = STORE.load(f) + ok("schemas", s.get("$id", "").endswith("/" + f), "%s: $id must end with its file name" % f) + try: + Draft202012Validator.check_schema(s) + meta = True + except SchemaError: + meta = False + ok("schemas", meta, "%s is not a valid draft 2020-12 schema" % f) + for f in js(p("registry", "formats.json"))["formats"]: + ok("schemas", os.path.exists(p("schemas", f["schema"])) or os.path.exists(p(f["schema"])), + "%s names a missing schema %s" % (f["format"], f["schema"])) + + +def valid(section, name, rec, where): + e = schema_errors(name, rec) + ok(section, not e, "%s: %s" % (where, e[:3])) + + +def check_registry(): + valid("registry", "stamps.schema.json", js(p("registry", "stamps", "scienting-stamps-1.json")), "stamps") + valid("registry", "stages.schema.json", js(p("registry", "stages", "scienting-stages-default.json")), "stages") + for rule in js(p("registry", "stamps", "scienting-stamps-1.json"))["rules"]: + re.compile(rule["pattern"]) + rules = {r["id"] for r in js(p("registry", "rules.json"))["rules"]} + for f in sorted(os.listdir(p("tools", "oracle"))): + if f.endswith(".py"): + for rule in re.findall(r'(?:Refusal|rep\.add)\(\s*"([a-z][a-z0-9.-]+)"', open(p("tools", "oracle", f)).read()): + if not rule.endswith("."): + ok("registry", rule in rules, "tools/oracle/%s raises %s, which is not in rules.json" % (f, rule)) + for v in ("text-hash", "match-hash", "align-key", "own-hash", "node-hash"): + ok("registry", "doc.hash." + v in rules, "doc.hash.%s is not in rules.json" % v) + # The character data the hashes depend on is pinned to one Unicode version (spec/01 §1.4). + ok("registry", unicodedata.unidata_version == "16.0.0", + "the tools run on Unicode %s, but the specification pins 16.0" % unicodedata.unidata_version) + for d in sorted(os.listdir(p("fixtures", "invalid"))): + ok("registry", js(p("fixtures", "invalid", d, "expect.json"))["rule"] in rules, "%s: rule is not in rules.json" % d) + + +def check_records(): + R = p("fixtures", "records") + roster = {k["id"]: k for k in js(os.path.join(R, "roster.json"))["keys"]} + for dirpath, _, files in os.walk(R): + if os.path.relpath(dirpath, R).split(os.sep)[0] == "log": + continue # the log's tiles and checkpoint are checked by check_log + for f in sorted(files): + path = os.path.join(dirpath, f) + rel = os.path.relpath(path, R) + if f.endswith(".csv"): + continue + if f.endswith(".jsonl"): + sch = {"annotations.jsonl": "annotation.schema.json", "draft-ids.jsonl": "draft-ids.schema.json", + "anchors.jsonl": "value-anchor.schema.json"}[f] + for i, rec in enumerate(jl(path), 1): + valid("records", sch, rec, "%s:%d" % (rel, i)) + continue + rec = js(path) + if f == "view.vl.json": + sch = "view.schema.json" + elif f == "layer.json": + sch = "layer.schema.json" + else: + sch = FORMAT_SCHEMA[rec["format"]] + valid("records", sch, rec, rel) + if rec.get("format") == "scienting-suspect/1": + ok("records", rec["id"] == record_id(sha256_hex(jcs.dumpb({k: v for k, v in rec.items() if k != "id"}))), + "%s: id does not derive" % rel) + if rec.get("signature"): + ok("records", RC.verify_signature(rec, roster), "%s: signature does not verify" % rel) + ok("records", rec["id"] == record_id(RC.record_hash(rec)), "%s: id does not derive" % rel) + ok("records", rec.get("by") == rec["signature"]["key"], "%s: by differs from the signing key" % rel) + ok("records", rec["format"] in RC.SIGNED_FORMATS, "%s: %s is not a signed format" % (rel, rec["format"])) + # A QA report is signed (spec/08 §8.9); a checklist is covered by its receipt at its hash (spec/08 §8.11). + ok("records", "signature" in js(os.path.join(R, "qa-report.json")), "the QA report is not signed") + cl = js(os.path.join(R, "checklist", "checklist.json")) + clr = js(os.path.join(R, "checklist", "receipt.json")) + cl_hash = sha256_hex(jcs.dumpb({k: v for k, v in cl.items() if k != "id"})) + ok("records", cl["id"] == record_id(cl_hash), "checklist id does not derive from its content hash") + ok("records", ["checklist", cl["id"], cl_hash] in clr["records"], "the checklist is not covered at its hash") + ok("records", RC.receipt_status(clr, [clr], roster) == "valid", "the checklist receipt is not valid") + ok("records", {i["result"] for i in cl["items"]} <= {"pass", "fail", "not-applicable"}, "checklist results") + # Proofs and the checkpoint (spec/08 §8.5, spec/11 §11.5, spec/23). + hale_receipts = {r["id"]: r for r in jl(p("fixtures", "packages", HALE, "receipts.jsonl"))} + pi = js(os.path.join(R, "proof-inclusion.json")) + rcp = hale_receipts.get(pi["receipt"]) + ok("records", rcp is not None and pi["item"] in crypto.receipt_items(rcp) and pi["root"] == rcp["root"] + and crypto.verify_inclusion(pi["root"], crypto.leaf_hash(pi["item"]), pi["index"], pi["size"], pi["path"]), + "the inclusion proof does not verify against its receipt") + pc = js(os.path.join(R, "proof-consistency.json")) + hist = PK.history_items(jl(p("fixtures", "packages", HALE, "corrections.jsonl"))) + ok("records", pc["to_root"] == js(p("fixtures", "packages", HALE, "document.json"))["history"] + and pc["from_root"] == crypto.history_root(hist[:pc["from_rev"]]) and pc["to_rev"] == len(hist) + and crypto.verify_consistency(pc["from_root"], pc["to_root"], pc["from_rev"], pc["to_rev"], pc["path"]), + "the consistency proof does not verify against the example's history") + cp = js(os.path.join(R, "checkpoint.json")) + note, verified = LG.verify_checkpoint(cp["note"], roster) + ok("records", note and note["origin"] == cp["origin"] and note["size"] == cp["size"] and note["root"] == cp["root"] + and verified == [sg["name"] for sg in cp["signatures"]], "the checkpoint note does not verify") + entries = [LG.entry(r) for r in hale_receipts.values()] + [LG.entry(js(os.path.join(R, "roster.json")))] + ok("records", LG.root(entries) == cp["root"], "the checkpoint root is not the root over the example's receipts") + # A project's settings.stages holds the id of a stage file. + stage_ids = {js(p("registry", "stages", f))["id"] for f in os.listdir(p("registry", "stages")) if f.endswith(".json")} + stages = js(os.path.join(R, "project.json")).get("settings", {}).get("stages") + ok("records", stages is None or stages in stage_ids, "project settings.stages names no stage file: %s" % stages) + # Confirmed annotations are covered by the layer receipt at their content hash. + lr = js(os.path.join(R, "layer", "receipt.json")) + items = {(k, i): h for k, i, h in lr["records"]} + for a in jl(os.path.join(R, "layer", "annotations.jsonl")): + sel = a["target"].get("selector", []) + anchors = [x["anchor"] for x in sel if x.get("type") == "AnchorSelector"] + for x in sel: + if x.get("type") == "TextQuoteSelector": + q = anchors[0].get("quote", {}) if anchors else {} + same = all(x.get(k, "") == q.get(k, "") for k in ("exact", "prefix", "suffix")) + ok("records", "exact" in q and same and set(x) <= {"type", "exact", "prefix", "suffix"}, + "a TextQuoteSelector must repeat the anchor's plain quote: " + a["id"]) + body = {k: v for k, v in a.items() if k not in ("status", "receipt", "modified")} + ok("records", a["id"].rsplit("/", 1)[1] == record_id(sha256_hex(jcs.dumpb( + {k: v for k, v in body.items() if k != "id"}))), "annotation id does not derive: " + a["id"]) + if a["status"] == "confirmed": + ok("records", items.get(("annotation", a["id"].rsplit("/", 1)[1])) == sha256_hex(jcs.dumpb(body)), + "a confirmed annotation is not covered at its hash: " + a["id"]) + ok("records", lr["root"] == crypto.merkle_root(crypto.receipt_items(lr)), "layer receipt root") + # Every figure of the main example has a confirmed description, which is what an accessible export needs. + anns = jl(os.path.join(R, "layer", "annotations.jsonl")) + described = {x["anchor"]["node"] for a in anns if a["body"]["kind"] == "description" and a["status"] == "confirmed" + for x in a["target"].get("selector", []) if x.get("type") == "AnchorSelector"} + figures = {n["id"] for n in jl(p("fixtures", "packages", HALE, "nodes.jsonl")) if n["kind"] == "figure"} + ok("records", figures and figures <= described, "a figure of the example has no confirmed description: %s" + % sorted(figures - described)) + ok("records", any(a["body"]["kind"] == "generated" and a["status"] == "proposed" for a in anns), + "the layer has no proposed generated annotation to contrast with the confirmed description") + + +def state_of(pkg): + return PK.read_state(pkg) + + +def check_packages(): + team_key = crypto.team_key(bytes.fromhex(open(p("fixtures", "keys", "smithlab-team-secret.hex")).read().strip())) + pk = p("fixtures", "packages") + for d in sorted(os.listdir(pk)): + if not os.path.isdir(os.path.join(pk, d)): + continue # the zipped form is checked by check_zips + rep = PK.validate(os.path.join(pk, d), STORE, team_key if d.endswith("checks-only") else None) + ok("packages", bool(rep), "%s: %s" % (d, rep.errors[:4])) + # The checks-only export carries exactly the HMAC values of the full document. + full = state_of(os.path.join(pk, HALE)).doc() + keyed = hashing.compute(full, hashing.Hasher(team_key)) + for n in jl(os.path.join(pk, HALE + ".checks-only", "nodes.jsonl")): + ok("packages", all(n[k] == keyed[n["id"]][k] for k in keyed[n["id"]]), "keyed values of " + n["id"]) + # Every reported value in the hale dataset is anchored to the cell that prints it, and resolves as current. + hp = os.path.join(pk, HALE) + st = state_of(hp) + ds = os.path.join(hp, "datasets", "ds-hale-bond-params") + desc = js(os.path.join(ds, "datapackage.json")) + valid("packages", "dataset.schema.json", desc, "ds-hale-bond-params") + rows = {} + with open(os.path.join(ds, "data.csv"), encoding="utf-8") as f: + head = f.readline().strip().split(",") + for ln in f: + vals = dict(zip(head, ln.rstrip("\n").split(","))) + rows[vals["key"]] = vals + doc = st.doc() + for va in jl(os.path.join(ds, "anchors.jsonl")): + valid("packages", "value-anchor.schema.json", va, "anchors.jsonl") + r = AN.resolve(st, va["anchor"]) + ok("packages", r["result"] == "current", "value anchor %s/%s is %s" % (va["row"], va["field"], r["result"])) + ok("packages", norm(hashing.plain(doc, r["node"])) == rows[va["row"]][va["field"]], + "CSV value differs from its cell: %s/%s" % (va["row"], va["field"])) + for m in jl(os.path.join(hp, "derived", "mathml.jsonl")): + valid("packages", "mathml.schema.json", m, "derived/mathml.jsonl") + + +def _zip(path, entries): + """Write a zip of (name, bytes, mode) entries the way a producer does (spec/12 §12.2).""" + with zipfile.ZipFile(path, "w") as zf: + for name, data, mode in entries: + zi = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0)) + zi.compress_type = zipfile.ZIP_STORED + zi.create_system = 3 + zi.external_attr = mode << 16 + zf.writestr(zi, data) + + +def check_zips(): + """Zipped packages (spec/12 §12.2 and §12.8). + + The fixture archive unpacks to the folder it was made from byte for byte, validates, keeps the producer's + byte-identical rules, and is reproduced by write_zip; crafted archives are refused with the rule named. + """ + pk = p("fixtures", "packages") + zips = [f for f in sorted(os.listdir(pk)) if f.endswith(PK.ZIP_EXTENSION)] + ok("zips", len(zips) >= 1, "no zipped package among the fixtures") + for z in zips: + key = z[:-len(PK.ZIP_EXTENSION)] + folder = os.path.join(pk, key) + rep = PK.validate_zip(os.path.join(pk, z), STORE) + ok("zips", bool(rep), "%s: %s" % (z, rep.errors[:4])) + with zipfile.ZipFile(os.path.join(pk, z)) as zf: + infos = zf.infolist() + names = [i.filename for i in infos] + ok("zips", names == sorted(names, key=lambda n: n.encode("utf-8")), "%s: entries are sorted by path" % z) + ok("zips", all(i.date_time == (1980, 1, 1, 0, 0, 0) and i.extra == b"" and not i.is_dir() + and i.compress_type in (zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED) for i in infos), + "%s: entries are dated 1980-01-01 00:00, carry no extra field and are stored or deflated" % z) + ok("zips", {n.partition("/")[0] for n in names} == {key}, "%s: one top-level folder named by the key" % z) + ok("zips", key + "/MANIFEST.json" in names, "%s: the manifest is an entry" % z) + with tempfile.TemporaryDirectory() as tmp: + root = PK.read_zip(os.path.join(pk, z), tmp) + ok("zips", _same_tree(folder, root), "%s: unpacks to its folder byte for byte" % z) + again = os.path.join(tmp, "again.zip") + PK.write_zip(root, again) + ok("zips", filecmp.cmp(again, os.path.join(pk, z), shallow=False), "%s: write_zip reproduces it" % z) + # Crafted archives, built from the tiny package. + tiny = p("fixtures", "packages", TINY_KEY) + entries = [] + for rel in sorted(os.path.relpath(os.path.join(d, f), tiny).replace(os.sep, "/") + for d, _, fs in os.walk(tiny) for f in fs): + with open(os.path.join(tiny, rel), "rb") as fh: + entries.append((TINY_KEY + "/" + rel, fh.read(), 0o644)) + cases = [ + ("two-folders", entries + [("other2026/x.txt", b"x", 0o644)], "package.zip.entry"), + ("duplicate", entries + [entries[0]], "package.zip.entry"), + ("folder-not-a-key", [("Tiny Example/" + n.partition("/")[2], d, m) for n, d, m in entries], "package.zip.entry"), + ("folder-not-the-key", [("other2026example/" + n.partition("/")[2], d, m) for n, d, m in entries], + "package.zip.entry"), + ("dot-dot", entries + [(TINY_KEY + "/assets/../../x", b"x", 0o644)], "package.zip.entry"), + ("symlink", entries + [(TINY_KEY + "/assets/link", b"document.json", 0o120777)], "package.zip.entry"), + ("no-folder", [(n.partition("/")[2], d, m) for n, d, m in entries], "package.zip.entry"), + ("directory-entries", entries + [(TINY_KEY + "/assets/", b"", 0o755)], None), + ] + with tempfile.TemporaryDirectory() as tmp: + for name, ents, rule in cases: + path = os.path.join(tmp, name + ".zip") + with __import__("warnings").catch_warnings(): + __import__("warnings").simplefilter("ignore") + _zip(path, ents) + rules = {e["rule"] for e in PK.validate_zip(path, STORE).errors} + ok("zips", (rule in rules) if rule else not rules, "%s: expected %s, got %s" % (name, rule, sorted(rules))) + ok("zips", {e["rule"] for e in PK.validate_zip(os.path.join(tmp, "directory-entries.zip"), STORE, limit=100).errors} + == {"package.zip.size"}, "an archive past the size limit is refused with package.zip.size") + with open(os.path.join(tmp, "not-a.zip"), "wb") as fh: + fh.write(b"PK\x03\x04 this is not an archive") + ok("zips", {e["rule"] for e in PK.validate_zip(os.path.join(tmp, "not-a.zip"), STORE).errors} + == {"package.zip.entry"}, "bytes that are not an archive are refused") + _zip(os.path.join(tmp, "empty.zip"), []) + ok("zips", {e["rule"] for e in PK.validate_zip(os.path.join(tmp, "empty.zip"), STORE).errors} + == {"package.zip.entry"}, "an empty archive is refused") + outside = [f for f in os.listdir(tmp) if not f.endswith(".zip")] + ok("zips", not outside, "reading archives wrote outside their folders: %s" % outside) + + +def check_owner_revocation(): + """A key the roster makes an owner may revoke anyone's receipt (spec/08 §8.7); any other key may not. + + No fixture has such a revocation, so this signs one: Ben revokes a receipt of Ana's, once with the + roster role owner and once as the editor he is. + """ + hp = p("fixtures", "packages", HALE) + revoker = "ben" + secret = bytes.fromhex(open(p("fixtures", "keys", revoker + ".ed25519.hex")).read().strip()) + roster_rec = js(os.path.join(hp, "roster.json")) + as_owner = dict(roster_rec, keys=[dict(k, role="owner") if k["id"] == revoker else k for k in roster_rec["keys"]]) + owner_roster = {k["id"]: k for k in as_owner["keys"]} + nodes = jl(os.path.join(hp, "nodes.jsonl")) + vals = {n["id"]: n for n in nodes} + document = js(os.path.join(hp, "document.json")) + recs, fidelity = jl(os.path.join(hp, "receipts.jsonl")), None + for target in recs: + if target["format"] != "scienting-receipt/1" or target["by"] == revoker: + continue + rev = RC.seal({"format": "scienting-revocation/1", "receipt": target["id"], "reason": "Owner check.", + "by": revoker, "at": "2026-10-13T00:00:00Z"}, secret, revoker) + trial = sorted(recs + [rev], key=lambda r: (r["at"], r["id"])) + fidelity = RC.distribution(RC.effective_levels(nodes, vals, trial, owner_roster)) + if fidelity != document["fidelity"]: + recs = trial + break + ok("packages", fidelity != document["fidelity"], "no receipt of the hale package matters to its levels") + document["fidelity"] = fidelity + manifest = js(os.path.join(hp, "MANIFEST.json")) + files, absent = {}, [f for f in manifest["files"] if f.get("present", True) is False] + for f in manifest["files"]: + if f.get("present", True): + with open(os.path.join(hp, f["path"]), "rb") as fh: + files[f["path"]] = fh.read() + files["receipts.jsonl"] = PK.jsonl(recs) + files["document.json"] = PK.line(document).encode("utf-8") + for roster, passes in ((as_owner, True), (roster_rec, False)): + files["roster.json"] = PK.line(roster).encode("utf-8") + with tempfile.TemporaryDirectory() as tmp: + PK.write(tmp, files, absent) + rules = {e["rule"] for e in PK.validate(tmp, STORE).errors} + role = next(k["role"] for k in roster["keys"] if k["id"] == revoker) + ok("packages", ("doc.fidelity.report" not in rules) == passes and rules <= {"doc.fidelity.report"}, + "a revocation by a key with the role %s: %s" % (role, sorted(rules))) + + +def check_unsafe_paths(): + """Loading and writing refuse manifest paths that leave the package, even without a prior validation.""" + with tempfile.TemporaryDirectory() as tmp: + pkg = os.path.join(tmp, "pkg") + shutil.copytree(p("fixtures", "packages", TINY_KEY), pkg) + manifest = js(os.path.join(pkg, "MANIFEST.json")) + for bad in ("../outside", "/etc/outside", "assets/../../outside"): + m = dict(manifest, files=[{"path": bad, "sha256": "0" * 64, "size": 1}] + manifest["files"]) + with open(os.path.join(pkg, "MANIFEST.json"), "w", encoding="utf-8") as f: + f.write(PK.line(m)) + conn = sqlite3.connect(":memory:") + db.create(conn, p("sql")) + try: + db.load(conn, pkg, os.path.join(tmp, "assets")) + rule = None + except Refusal as e: + rule = e.rule + ok("packages", rule == "package.path.unsafe", "load accepted the manifest path %r" % bad) + try: + PK.write(os.path.join(tmp, "out"), {bad: b"x", "document.json": b"{}"}) + rule = None + except Refusal as e: + rule = e.rule + ok("packages", rule == "package.path.unsafe", "write accepted the path %r" % bad) + ok("packages", not os.path.exists(os.path.join(tmp, "outside")), "a file was written outside the package") + + +def reference_values(doc, hasher=hashing.PLAIN): + """The five values the slow way: every node projected from its whole subtree, as spec/05 §5.1 reads. + + The oracle's hashing.Index joins its children's cached projections and rehashes only what a correction + changed; this independent computation must always agree with it. + """ + values = {} + for nid in reversed(doc.preorder()): + st, _ = hashing.strict(doc, nid) + own = hasher(jcs.dumpb(hashing.own_content(doc, nid, lambda x: values[x]["text_hash"]))) + values[nid] = {"text_hash": hasher(norm(hashing.plain(doc, nid))), "match_hash": hasher(st), + "align_key": hasher(hashing.lossy_from_strict(st)), "own_hash": own, + "node_hash": hasher(jcs.dumpb({"own": own, "children": [ + values[c]["node_hash"] for c in doc.kids(nid)]}))} + return values + + +def check_incremental(): + """After every correction of every fixture source, the incrementally kept values equal the slow ones.""" + from tools.build import Names, build_document + team = hashing.Hasher(crypto.team_key(bytes.fromhex( + open(p("fixtures", "keys", "smithlab-team-secret.hex")).read().strip()))) + Names.registry.clear() + # Sorted, the main example comes first, so the draft's references to its sentences resolve. + for f in sorted(os.listdir(p("fixtures", "src"))): + if not f.endswith(".json"): + continue + src = js(p("fixtures", "src", f)) + src["name"] = f[:-len(".json")] # the name other sources refer to, as the builder sets it + _, _, _, _, states, _ = build_document(src) + keyed = None + for rev in sorted(states): + st = states[rev] + ok("packages", st.index().values == reference_values(st.doc()), + "%s rev %d: incremental values differ from the full computation" % (f, rev)) + # The keyed values, carried forward from revision 0 by updates alone. + keyed = hashing.Index.build(st.doc(), team) if keyed is None else keyed.update(st.doc()) + ok("packages", keyed.values == reference_values(st.doc(), team), + "%s rev %d: incremental keyed values differ from the full computation" % (f, rev)) + Names.registry.clear() + + +def check_gate(): + """The gate runs on a proposal against a package's current state and leaves that state unchanged.""" + st = state_of(p("fixtures", "packages", HALE)) + before = json.dumps(st.nodes, sort_keys=True) + target = next(n for n in st.nodes if n["kind"] == "sentence" and "Each bond" in hashing.plain(st.doc(), n["id"])) + base = {"format": "scienting-correction/1", "evidence": [{"kind": "person", "by": "ana"}], "author": {"key": "ana"}, + "reason": "Gate check.", "at": "2026-10-14T09:00:00Z", "status": "proposed"} + st1, rec = CO.gate(st, dict(base, op="replace", target=target["id"], find="Each bond", replace="Every bond"), STORE) + ok("packages", rec["index"] == st.rev + 1 and st1.rev == st.rev + 1, "the gate's record has the next index") + ok("packages", json.dumps(st.nodes, sort_keys=True) == before, "the gate changed the state it was given") + valid("packages", "correction.schema.json", rec, "gate record") + crop = [{"kind": "crop", "sha256": "0" * 64}] + cell = next(n for n in st.nodes if n["kind"] == "cell") + section = next(n for n in st.nodes if n["kind"] == "section" and "label" in n) + header = next(c["header_path"][0] for n in st.nodes if n["kind"] == "table" for c in n["attrs"]["columns"]) + for bad, rule in (({"op": "replace", "target": target["id"]}, "correction.schema"), + (dict(base, op="replace", target=target["id"], find="0.01", replace="0.02"), "correction.digits"), + (dict(base, op="insert", target=target["id"], run=9, offset=0, text="x", evidence=crop), + "correction.insert"), + # Rule 11 of spec/11 §11.4: the result keeps to chapter 3, attribute shapes included. + (dict(base, op="set", target=cell["id"], attr="colspan", value="2"), "doc.node.attrs"), + (dict(base, op="set", target=cell["id"], attr="role", value="boss"), "doc.node.attrs"), + (dict(base, op="insert", parent=target["parent"], place_after=target["id"], evidence=crop, + node={"kind": "sentence", "content": [{"kind": "text", "text": "Junk."}], "foo": 1}), + "doc.node.schema"), + (dict(base, op="delete", target=header), "doc.table.header")): + try: + CO.gate(st, bad, STORE) + got = None + except Refusal as e: + got = e.rule + ok("packages", got == rule, "the gate gave %s for a proposal that breaks %s" % (got, rule)) + # A relabel to null removes the label instead of writing null (spec/03 §3.1). + st2, _ = CO.gate(st, dict(base, op="relabel", target=section["id"], label=None, evidence=crop), STORE) + ok("packages", "label" not in next(n for n in st2.nodes if n["id"] == section["id"]), "relabel to null drops the label") + + +def check_invalid(): + base = p("fixtures", "invalid") + for d in sorted(os.listdir(base)): + expect = js(os.path.join(base, d, "expect.json"))["rule"] + zipped = os.path.join(base, d, "package" + PK.ZIP_EXTENSION) + rep = PK.validate_zip(zipped, STORE) if os.path.exists(zipped) else PK.validate(os.path.join(base, d, "package"), STORE) + rules = {e["rule"] for e in rep.errors} + ok("invalid", expect in rules, "%s: expected %s, got %s" % (d, expect, sorted(rules) or "no error")) + + +def V(name): + return jl(p("vectors", name)) + + +ROSTER_BY_ID_CHECK = {k["id"]: k for k in js(p("fixtures", "records", "roster.json"))["keys"]} + + +def check_vectors(): + from tools.build import parse_doubles, projection_case, sentence_doc + for c in V("canonical-json.jsonl"): + ok("vectors", jcs.dumps(parse_doubles(c["input_json"])) == c["output"], "canonical-json " + c["id"]) + for c in V("normalize.jsonl"): + ok("vectors", norm(c["input"]) == c["output"] and sha256_hex(c["output"]) == c["sha256"], "normalize " + c["id"]) + for c in V("ids.jsonl"): + if "digest" in c: + d = bytes.fromhex(c["digest"]) + ok("vectors", letter_first(d, 7) == c["node_id"] and record_id(c["digest"]) == c["record_id"], c["id"]) + else: + ok("vectors", mint_node_id(c["doc"], c["kind"], c["text_hash"], c["occurrence"]) == c["node_id"] + and jcs.dumps(["scienting-id/1", c["doc"], c["kind"], c["text_hash"], c["occurrence"]]) == c["payload"], + c["id"]) + for c in V("notation.jsonl"): + ok("vectors", fold_math(c["notation"], c["source"]) == c["canonical"], "notation " + c["id"]) + byid = {} + for c in V("projections.jsonl"): + again = projection_case(c["id"], c["runs"], c.get("note")) + ok("vectors", again == c, "projection " + c["id"]) + byid[c["id"]] = c + for g in V("projection-groups.jsonl"): + field = g.get("same") or g.get("differ") + values = {byid[x][field] for x in g["cases"]} + ok("vectors", len(values) == 1 if "same" in g else len(values) == len(g["cases"]), "group " + g["id"]) + for c in V("offsets.jsonl"): + doc, s = sentence_doc(c["runs"]) + t = hashing.plain(doc, s) + ok("vectors", t == c["plain"] and t[c["span"][0]:c["span"][1]] == c["exact"] + and [cp_to_utf16(t, x) for x in c["span"]] == c["utf16_span"], "offsets " + c["id"]) + ok("vectors", t.encode("utf-16-le")[2 * c["utf16_span"][0]:2 * c["utf16_span"][1]].decode("utf-16-le") + == c["exact"], "offsets utf16 " + c["id"]) + for c in V("hashes.jsonl"): + d = Doc(c["doc"], c["nodes"]) + vals = hashing.compute(d) + ok("vectors", vals == c["values"], "hashes " + c["id"]) + for nid, o in c["own_content"].items(): + ok("vectors", sha256_hex(jcs.dumpb(o)) == vals[nid]["own_hash"], "own content " + nid) + for c in V("addresses.jsonl"): + ok("vectors", AN.parse_address(c["address"]) == c["parsed"], "address " + c["id"]) + if c["parsed"]: + q = c["parsed"] + ok("vectors", AN.format_address(q["store"], q["key"], q["node"], q["pin"], q["span"]) == c["address"], + "address round trip " + c["id"]) + kv = {c["id"]: c for c in V("keyed.jsonl")} + k = crypto.team_key(bytes.fromhex(kv["team-key"]["secret"])) + ok("vectors", k.hex() == kv["team-key"]["key"] and crypto.key_id(k) == kv["team-key"]["key_id"], "team key") + ok("vectors", hashing.Hasher(k)(kv["team-hmac-text"]["text"]) == kv["team-hmac-text"]["text_hash_keyed"], "hmac") + ok("vectors", [crypto.page_hash(f) for f in kv["page-hashes"]["page_fps"]] == kv["page-hashes"]["page_hashes"], + "page hashes") + pkk = crypto.page_key(kv["page-key"]["page_fps"], kv["page-key"]["context"]) + ok("vectors", pkk.hex() == kv["page-key"]["key"] and hashing.Hasher(pkk)(kv["page-key"]["quote"]) + == kv["page-key"]["quote_mac"], "page key") + nh = kv["non-holder"] + ok("vectors", sha256_hex(nh["guess"]) != nh["quote_mac"] and crypto.page_key(nh["wrong_page_fps"], kv["page-key"][ + "context"]).hex() == nh["wrong_key"] != kv["page-key"]["key"], "non-holder") + stamps = js(p("registry", "stamps", "scienting-stamps-1.json"))["rules"] + fpv = {c["id"]: c for c in V("fingerprints.jsonl")} + for c in fpv.values(): + fp, removed = FP.fingerprint(c["page"], stamps) + ok("vectors", fp == c["page_fp"] and removed == c["removed"], "fingerprint " + c["id"]) + ok("vectors", fpv["acs-download-1"]["page_fp"] == fpv["acs-download-2"]["page_fp"], "ACS downloads share a page") + ok("vectors", fpv["wiley-download-1"]["page_fp"] == fpv["wiley-download-2"]["page_fp"], "Wiley downloads share") + ok("vectors", fpv["acs-download-1"]["page_fp"] != fpv["acs-changed-text"]["page_fp"], "a changed page differs") + for c in V("merkle.jsonl"): + ok("vectors", crypto.merkle_root(c["items"]) == c["root"], "merkle " + c["id"]) + for c in V("signatures.jsonl"): + if "did" in c: + ok("vectors", crypto.did_key(c["scheme"], bytes.fromhex(c["public"])) == c["did"], c["id"]) + elif c["id"].startswith("ml-dsa-65"): + pk, sk = mldsa.keygen(bytes.fromhex(c["seed"])) + ok("vectors", pk.hex() == c["public"], c["id"] + ": key generation") + if "signature" in c: + sig = bytes.fromhex(c["signature"]) + ok("vectors", mldsa.sign(sk, bytes.fromhex(c["message"])) == sig and mldsa.verify(pk, bytes.fromhex(c["message"]), sig) + and not mldsa.verify(pk, b"x", sig), c["id"] + ": signature") + elif "secret" in c: + sk = bytes.fromhex(c["secret"]) + ok("vectors", crypto.ed25519_public(sk).hex() == c["public"] + and crypto.ed25519_sign(sk, c["message"].encode()).hex() == c["signature"], c["id"]) + else: + r = c["receipt"] + ok("vectors", RC.record_hash(r) == c["record_hash"] and RC.signing_payload(r).decode() == c["payload"] + and crypto.ed25519_verify(base64.b64decode(c["public"]), c["payload"].encode(), + base64.b64decode(r["signature"]["value"])), c["id"]) + for c in V("spotcheck.jsonl"): + ok("vectors", RC.sample_size(c["n"], c["rate"], c["minimum"]) == c["size"], "sample size " + c["id"]) + if "seed" in c: + seed = base64.b64decode(c["seed"]) + beta = vrf.verify(base64.b64decode(c["checker_public"]), c["seed_payload"].encode(), seed) + ok("vectors", beta is not None and beta.hex() == c["beta"] + and RC.sample(c["receipt"], seed, c["rate"], c["minimum"]) == c["sample"], "spot-check " + c["id"]) + for c in V("bounds.jsonl"): + ok("vectors", RC.bound_string(c["errors"], c["sampled"], c["confidence"]) == c["bound"], "bound " + c["id"]) + ok("vectors", Fraction(next(c for c in V("bounds.jsonl") if c["id"] == "k0-n300")["bound"]) < Fraction(1, 100), + "zero errors in 300 bounds the rate below 1%") + for c in V("alignment.jsonl"): + ok("vectors", AL.align(c["a"], c["b"]) == c["expect"], "alignment " + c["id"]) + for c in V("corrections.jsonl"): + st = CO.State(c["doc"], [{k: v for k, v in n.items() if k not in ( + "text_hash", "match_hash", "align_key", "own_hash", "node_hash")} for n in c["before"]["nodes"]]) + try: + st1, rec = CO.apply(st, c["correction"], store=STORE) + v1 = hashing.compute(st1.doc()) + ok("vectors", st1.index().values == reference_values(st1.doc()), + "correction %s: incremental values differ from the full computation" % c["id"]) + got = {"record": rec, "nodes": [dict(n, **v1[n["id"]]) for n in st1.nodes], "ids": st1.ids} + except Refusal as e: + got = {"refusal": e.rule} + ok("vectors", got == c["expect"], "correction " + c["id"]) + states = {} + for c in V("resolve.jsonl"): + st = states.setdefault(c["package"], state_of(p(c["package"]))) + valid("vectors", "anchor.schema.json", c["anchor"], "resolve " + c["id"]) + ok("vectors", AN.resolve(st, c["anchor"]) == c["expect"], "resolve " + c["id"]) + results = {c["expect"]["result"] for c in V("resolve.jsonl")} + ok("vectors", results == {"current", "changed-below", "moved", "reattached", "stale"}, "all five results occur") + for c in V("rights.jsonl"): + if "stage" in c: + w = {"rights": c["rights"], "origin": c["origin"], "sha256": c["witness_sha256"]} + uses, expired = RI.effective(w, c["policies"], c["now"]) + allowed, lacking = RI.check(c["requires"], c["processor"], uses) + ok("vectors", {"allowed": allowed, "lacking": lacking, "expired": expired} == c["expect"], "rights " + c["id"]) + elif "backend" in c: + a, f = RI.backend_allowed(c["backend"], c["profile"]) + ok("vectors", {"allowed": a, "failed": f} == c["expect"], "rights " + c["id"]) + else: + ok("vectors", RI.combine([RI.flat(r) for r in c["rights"]]) == c["expect"], "rights " + c["id"]) + for c in V("grading.jsonl"): + st = states.setdefault(c["package"], state_of(p(c["package"]))) + ok("vectors", GR.grade(c["exercise"], c["submission"], st) == c["expect"], "grading " + c["id"]) + sets = {} + for c in V("targets.jsonl"): + st = states.setdefault(c["package"], state_of(p(c["package"]))) + got = TG.target_set(st.doc(), c["anchored"], c["digit_rule"]) + ok("vectors", got == c["expect"]["nodes"], "targets " + c["id"]) + sets[c["digit_rule"]] = {n for n, _ in got} + d = st.doc() + ok("vectors", all(d.nodes[n]["kind"] in TG.MATH_KINDS for n, r in got if r == "equation") + and all(d.nodes[n]["kind"] in TG.LEAVES for n, _ in got), "targets %s: only leaves, equations by kind" % c["id"]) + ok("vectors", set(sets) == set(TG.DIGIT_RULES) and sets["none"] <= sets["anchored-sections"] <= sets["all"] + and sets["none"] < sets["all"], "the three digit rules nest") + for c in V("keys.jsonl"): + if "version" in c: + ok("vectors", K.document_key(c["work_key"], c["version"]) == c["document_key"], "keys " + c["id"]) + elif "taken" in c: + ok("vectors", K.unique_work_key(c["same_as"], c["meta"], set(c["taken"])) == c["key"] + and len(c["key"].rsplit("-", 1)[1]) == 6, "keys " + c["id"]) + else: + ident = K.identity(c["same_as"], c["meta"]) + ok("vectors", ident == c["identity"] and K.scholar_part(c["meta"]) == c["scholar"] + and K.SCHEME + ":" + ident == c["payload"] and sha256_hex(c["payload"]) == c["sha256"] + and K.suffix(ident) == c["suffix"] and K.suffix(ident, 8) == c["suffix_8"] + and c["suffix_8"].startswith(c["suffix"]) and K.work_key(c["same_as"], c["meta"]) == c["key"] + and K.WORK_KEY_RE.match(c["key"]) and c["key"] == c["scholar"] + "-" + c["suffix"], "keys " + c["id"]) + for c in V("proofs.jsonl"): + items = c["items"] + if c["kind"] == "root": + ok("vectors", crypto.history_root(items) == c["root"] == crypto.EMPTY_ROOT, "proofs " + c["id"]) + elif c["kind"] == "inclusion": + ok("vectors", crypto.inclusion_path(items, c["index"]) == c["path"] + and crypto.leaf_hash(items[c["index"]]) == c["leaf"] + and crypto.verify_inclusion(c["root"], c["leaf"], c["index"], c["size"], c["path"]), "proofs " + c["id"]) + other = (c["index"] + 1) % c["size"] + ok("vectors", c["size"] == 1 or not crypto.verify_inclusion(c["root"], c["leaf"], other, c["size"], c["path"]), + "proofs %s: the path proves another index" % c["id"]) + else: + ok("vectors", crypto.consistency_proof(items, c["from"]) == c["path"] + and crypto.history_root(items[:c["from"]]) == c["from_root"] + and crypto.verify_consistency(c["from_root"], c["to_root"], c["from"], c["to"], c["path"]), "proofs " + c["id"]) + ok("vectors", c["from"] == 0 or not crypto.verify_consistency(c["from_root"], "0" * 64, c["from"], c["to"], c["path"]), + "proofs %s: a wrong root passes" % c["id"]) # every tree extends the empty one, so m = 0 proves nothing + for c in V("vrf.jsonl"): + pub, alpha, proof = bytes.fromhex(c["public"]), bytes.fromhex(c["alpha"]), bytes.fromhex(c["proof"]) + if "secret" in c: + sk = bytes.fromhex(c["secret"]) + ok("vectors", vrf.public_key(sk) == pub == crypto.ed25519_public(sk) and vrf.prove(sk, alpha) == proof, + "vrf %s: prove" % c["id"]) + beta = vrf.verify(pub, alpha, proof) + ok("vectors", (beta.hex() if beta else None) == c["beta"], "vrf %s: verify" % c["id"]) + if c["beta"]: + ok("vectors", vrf.proof_to_hash(proof).hex() == c["beta"], "vrf %s: proof_to_hash" % c["id"]) + ok("vectors", any(c["id"] == "rfc9381-example-16" and c["proof"].startswith("8657106690b5526245a92b003bb079cc") + and c["beta"].startswith("90cf1df3b703cce59e2a35b925d41116") for c in V("vrf.jsonl")), + "the RFC 9381 example is not reproduced") + from tools.build import secret + for c in V("checkpoint.jsonl"): + ok("vectors", LG.root(c["entries"]) == c["root"], "checkpoint %s: root" % c["id"]) + signers = [(n, secret(n)) for n in c["signers"]] + ok("vectors", LG.sign_checkpoint(c["origin"], c["entries"], signers) == c["note"], "checkpoint %s: note" % c["id"]) + note, verified = LG.verify_checkpoint(c["note"], ROSTER_BY_ID_CHECK) + ok("vectors", note and note["size"] == len(c["entries"]) and note["root"] == c["root"] and verified == c["signers"], + "checkpoint %s: verify" % c["id"]) + bad = c["note"].replace(c["origin"], c["origin"] + "x", 1) + ok("vectors", LG.verify_checkpoint(bad, ROSTER_BY_ID_CHECK)[1] == [], "checkpoint %s: a changed note verifies" % c["id"]) + ok("vectors", sorted(LG.tiles(c["entries"])) == c["tiles"], "checkpoint %s: tile paths" % c["id"]) + + +def check_determinism(): + with tempfile.TemporaryDirectory() as tmp: + subprocess.run([sys.executable, p("tools", "build.py"), "--out", tmp], check=True) + for sub in ("fixtures", "vectors"): + # Files the repository ignores, such as macOS's .DS_Store, are not part of the build. + cmp = filecmp.dircmp(p(sub), os.path.join(tmp, sub), ignore=filecmp.DEFAULT_IGNORES + [".DS_Store"]) + diffs = [] + + def walk(c, prefix): + for f in c.left_only + c.right_only + c.diff_files + c.funny_files: + if f != "README.md" and not (prefix == "fixtures/" and f == "src"): + diffs.append(prefix + f) + for f in c.common_files: + if not filecmp.cmp(os.path.join(c.left, f), os.path.join(c.right, f), shallow=False): + diffs.append(prefix + f) + for name, s in c.subdirs.items(): + walk(s, prefix + name + "/") + + walk(cmp, sub + "/") + ok("determinism", not diffs, "rebuild differs: %s" % sorted(set(diffs))[:5]) + + +RESERVED = set(""" +ABORT ACTION ADD AFTER ALL ALTER ALWAYS ANALYZE AND ANY ARRAY AS ASC ASENSITIVE AT ATTACH AUTHORIZATION AUTOINCREMENT +BEFORE BEGIN BETWEEN BIGINT BINARY BLOB BOTH BY CALL CASCADE CASE CAST CHANGE CHAR CHARACTER CHECK COLLATE COLUMN +COMMIT CONDITION CONFLICT CONSTRAINT CONTINUE CONVERT CREATE CROSS CUBE CUME_DIST CURRENT CURRENT_DATE CURRENT_ROLE +CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR DATABASE DATABASES DEC DECIMAL DECLARE DEFAULT DEFERRABLE DEFERRED +DELAYED DELETE DENSE_RANK DESC DESCRIBE DETACH DETERMINISTIC DISTINCT DISTINCTROW DIV DO DOUBLE DROP DUAL EACH ELSE +ELSEIF EMPTY ENCLOSED END ESCAPE ESCAPED EXCEPT EXCLUDE EXCLUSIVE EXISTS EXIT EXPLAIN FAIL FALSE FETCH FILTER FIRST +FIRST_VALUE FLOAT FOLLOWING FOR FORCE FOREIGN FREEZE FROM FULL FULLTEXT FUNCTION GENERATED GET GLOB GRANT GROUP +GROUPING GROUPS HAVING HIGH_PRIORITY IF IGNORE ILIKE IMMEDIATE IN INDEX INDEXED INFILE INITIALLY INNER INOUT +INSENSITIVE INSERT INSTEAD INT INTEGER INTERSECT INTERVAL INTO IS ISNULL ITERATE JOIN JSON_TABLE KEY KEYS KILL LAG LAST +LAST_VALUE LATERAL LEAD LEADING LEAVE LEFT LIKE LIMIT LINEAR LINES LOAD LOCALTIME LOCALTIMESTAMP LOCK LONG LOOP +LOW_PRIORITY MATCH MATERIALIZED MAXVALUE MOD MODIFIES NATURAL NO NOT NOTHING NOTNULL NTH_VALUE NTILE NULL NULLS NUMERIC +OF OFFSET ON ONLY OPTIMIZE OPTION OPTIONALLY OR ORDER OTHERS OUT OUTER OVER OVERLAPS PARTITION PERCENT_RANK PLACING PLAN +PRAGMA PRECEDING PRECISION PRIMARY PROCEDURE PURGE QUERY RAISE RANGE RANK READ READS REAL RECURSIVE REFERENCES REGEXP +REINDEX RELEASE RENAME REPEAT REPLACE REQUIRE RESIGNAL RESTRICT RETURN RETURNING REVOKE RIGHT RLIKE ROLLBACK ROW ROWS +ROW_NUMBER SAVEPOINT SCHEMA SCHEMAS SELECT SENSITIVE SEPARATOR SESSION_USER SET SHOW SIGNAL SIMILAR SMALLINT SOME +SPATIAL SPECIFIC SQL SQLEXCEPTION SQLSTATE SQLWARNING SSL STARTING STORED STRAIGHT_JOIN SYMMETRIC SYSTEM SYSTEM_USER +TABLE TABLESAMPLE TEMP TEMPORARY TERMINATED THEN TIES TINYINT TO TRAILING TRANSACTION TRIGGER TRUE UNBOUNDED UNDO +UNION UNIQUE UNLOCK UNSIGNED UPDATE USAGE USE USER USING UTC_DATE UTC_TIME UTC_TIMESTAMP VACUUM VALUES VARBINARY +VARCHAR VARCHARACTER VARIADIC VARYING VERBOSE VIEW VIRTUAL WHEN WHERE WHILE WINDOW WITH WITHOUT WRITE XOR ZEROFILL +""".split()) + + +def check_sql(): + ddl = "" + for f in ("doc.sql", "store.sql", "bundle-sqlite.sql"): + ddl += open(p("sql", f), encoding="utf-8").read() + "\n" + for m in re.finditer(r"CREATE (?:VIRTUAL )?TABLE (\w+)\s*(?:USING fts5)?\(\n(.*?)\n\);", ddl, re.S): + names = [m.group(1)] + [ln.strip().split()[0] for ln in m.group(2).splitlines() + if ln.strip() and not ln.strip().startswith(("PRIMARY", "--", "'", "tokenize"))] + for n in names: + ok("sql", n.upper() not in RESERVED, "%s uses the reserved word %s" % (m.group(1), n)) + for m in re.finditer(r"CREATE INDEX (\w+) ON", ddl): + ok("sql", m.group(1).upper() not in RESERVED, "index name " + m.group(1)) + ok("sql", "FOREIGN KEY" not in ddl and "REFERENCES" not in ddl, "no foreign keys") + with tempfile.TemporaryDirectory() as tmp: + conn = sqlite3.connect(os.path.join(tmp, "bundle.db")) + db.create_bundle(conn, p("sql")) + assets = os.path.join(tmp, "assets") + pk = p("fixtures", "packages") + for d in sorted(os.listdir(pk)): + if not os.path.isdir(os.path.join(pk, d)): + continue + key = db.load(conn, os.path.join(pk, d), assets) if not d.endswith("checks-only") else None + if key is None: + # A second load of the same key goes to its own database. + c2 = sqlite3.connect(":memory:") + db.create_bundle(c2, p("sql")) + key = db.load(c2, os.path.join(pk, d), assets) + ok("sql", db.index(c2, key) == 0, "%s: withheld text was indexed" % d) + h = db.unload(c2, key, os.path.join(tmp, "out", d), assets) + else: + db.index(conn, key) + h = db.unload(conn, key, os.path.join(tmp, "out", d), assets) + same = _same_tree(os.path.join(pk, d), os.path.join(tmp, "out", d)) + ok("sql", same, "%s: unload is not byte-identical" % d) + with open(os.path.join(pk, d, "MANIFEST.json"), "rb") as f: + ok("sql", sha256_hex(f.read()) == h, "%s: package hash differs after unload" % d) + check_bundle(conn) + # Store records satisfy the store tables' CHECK constraints. + R = p("fixtures", "records") + lay = js(os.path.join(R, "layer", "layer.json")) + conn.execute("INSERT INTO layers VALUES (?,?,?,?,?,?,?,?)", + (lay["id"], lay.get("project"), lay["label"], lay["purpose"], lay.get("audience"), + lay["visibility"], jcs.dumps(lay["license"]), jcs.dumps(lay))) + for a in jl(os.path.join(R, "layer", "annotations.jsonl")): + conn.execute("INSERT INTO annotations VALUES (?,?,?,?,?,?,?,?)", + (a["id"], a["layer"], a["body"]["kind"], a["status"], a.get("receipt"), a["creator"]["id"], + a["created"], jcs.dumps(a))) + prj = js(os.path.join(R, "project.json")) + conn.execute("INSERT INTO projects VALUES (?,?,?,?,?,?,?)", + (prj["key"], prj.get("store"), prj["name"], prj.get("description"), jcs.dumps(prj.get("claims")), + jcs.dumps(prj.get("settings")), jcs.dumps(prj))) + for m in prj["members"]: + conn.execute("INSERT INTO members VALUES (?,?,?,?)", (prj["key"], m["person"], m["role"], jcs.dumps(m["keys"]))) + for k in js(os.path.join(R, "roster.json"))["keys"]: + conn.execute("INSERT INTO roster_keys VALUES (?,?,?,?,?,?,?,?,?,?)", + ("smithlab", k["id"], jcs.dumps(k["person"]), k["role"], k["scheme"], k["public"], k.get("did"), + jcs.dumps(k["purposes"]), k["registered_at"], k["revoked_at"])) + dg = js(os.path.join(R, "digitization.json")) + conn.execute("INSERT INTO digitizations VALUES (?,?,?,?,?,?,?,?)", + (dg["id"], dg["doc"], dg["target"]["anchor"]["node"], dg["target"].get("page_fp"), + dg["method"]["kind"], dg["confirmation"], dg.get("dataset"), jcs.dumps(dg))) + conn.commit() + ok("sql", True, "store records loaded") + + +def check_bundle(conn): + """The bundle's search index and metadata (spec/13 §13.5), built by the oracle's db.index and db.write_meta.""" + units = dict(conn.execute("SELECT unit, COUNT(*) FROM search GROUP BY unit").fetchall()) + for u in ("sentence", "cell", "figure-text"): + ok("sql", units.get(u, 0) > 0, "the search index has no %s rows" % u) + # No fixture has an equation outside a sentence, so a small document shows both kinds of equation. + nodes = [{"id": "d", "kind": "document", "parent": None, "ord": 0}, + {"id": "p", "kind": "paragraph", "parent": "d", "ord": 0}, + {"id": "s", "kind": "sentence", "parent": "p", "ord": 0, + "content": [{"kind": "text", "text": "Then "}, {"kind": "equation", "node": "e1"}]}, + {"id": "e1", "kind": "equation", "parent": "s", "ord": 0, "content": {"notation": "tex", "source": "a=b"}}, + {"id": "e2", "kind": "equation", "parent": "p", "ord": 1, "content": {"notation": "tex", "source": "c=d"}}] + got = [(n, u, c) for _, n, u, c, _ in db.search_rows("k", nodes)] + ok("sql", got == [("s", "sentence", "paragraph"), ("e2", "equation", "paragraph")], + "search rows for a sentence with an inline equation and a display equation: %s" % got) + ok("sql", set(units) <= {"sentence", "cell", "equation", "figure-text"}, "unknown search units %s" % sorted(units)) + expect = conn.execute( + "SELECT COUNT(*) FROM nodes n LEFT JOIN nodes q ON q.doc_key = n.doc_key AND q.id = n.parent " + "WHERE n.withheld IS NULL AND (n.kind IN ('sentence', 'cell') OR (n.kind = 'equation' AND q.kind <> 'sentence'))" + ).fetchone()[0] + ok("sql", sum(v for u, v in units.items() if u != "figure-text") == expect, + "the search index does not have one row per sentence, cell and equation outside a sentence") + inner = conn.execute( + "SELECT COUNT(*) FROM search s JOIN nodes n ON n.doc_key = s.doc_key AND n.id = s.node " + "JOIN nodes q ON q.doc_key = n.doc_key AND q.id = n.parent WHERE n.kind = 'equation' AND q.kind = 'sentence'" + ).fetchone()[0] + ok("sql", inner == 0, "an equation inside a sentence is indexed apart from its sentence") + bad = conn.execute( + "SELECT COUNT(*) FROM search s JOIN nodes n ON n.doc_key = s.doc_key AND n.id = s.node " + "LEFT JOIN nodes q ON q.doc_key = n.doc_key AND q.id = n.parent " + "WHERE s.unit <> 'figure-text' AND s.context IS NOT q.kind").fetchone()[0] + ok("sql", bad == 0, "a search row's context is not the kind of its node's parent") + hits = conn.execute("SELECT node FROM search WHERE search MATCH 'scanned'").fetchall() + ok("sql", len(hits) == 1, "full-text search finds the merged sentence") + hits = conn.execute("SELECT context FROM search WHERE unit = 'sentence' AND search MATCH 'Methods'").fetchall() + ok("sql", ("heading",) in hits, "a heading sentence is indexed with the context heading") + stores = [r[0] for r in conn.execute("SELECT DISTINCT store FROM documents WHERE store IS NOT NULL")] + db.write_meta(conn, stores[0] if len(stores) == 1 else "", "fixtures/packages") + meta = dict(conn.execute("SELECT name, value FROM bundle_meta").fetchall()) + ok("sql", {"format", "store", "built_from", "spec"} <= set(meta), "bundle_meta lacks a required name") + ok("sql", meta["format"] in FORMAT_SCHEMA, "bundle_meta names an unregistered format") + top = re.search(r"^## (\S+)", open(p("CHANGELOG.md"), encoding="utf-8").read(), re.M).group(1) + ok("sql", meta["spec"] == top, "bundle_meta spec %s is not the changelog's latest version %s" % (meta["spec"], top)) + + +def _same_tree(a, b): + fa = sorted(os.path.relpath(os.path.join(d, f), a) for d, _, fs in os.walk(a) for f in fs) + fb = sorted(os.path.relpath(os.path.join(d, f), b) for d, _, fs in os.walk(b) for f in fs) + return fa == fb and all(filecmp.cmp(os.path.join(a, f), os.path.join(b, f), shallow=False) for f in fa) + + +UK = re.compile(r"\b(\w*(?:colour|behaviour|favour|honour|labour|neighbour|centre|metre|litre|fibre|analys(?:e|ed|es|ing)|" + r"catalogue|licence|defence|offence|organis\w*|normalis\w*|recognis\w*|optimis\w*|minimis\w*|" + r"maximis\w*|standardis\w*|serialis\w*|canonicalis\w*|initialis\w*|summaris\w*|prioritis\w*|" + r"emphasis(?:e|ed|es|ing)|realis(?:e|ed|es|ing)|travell\w*|modell(?:ed|ing)|labell(?:ed|ing)|" + r"cancell(?:ed|ing)|signall(?:ed|ing)|programme|grey|whilst|amongst|towards|judgement|ageing|" + r"artefact)\w*)\b", re.I) +SENTENCE_BREAK = re.compile(r"[a-z0-9)\]*_`'\"]\. [A-Z]") +ABBREV = re.compile(r"\b(e\.g|i\.e|et al|cf|vs|Fig|Eq|Ref|ca|No|St|Dr|Mr|Ms|al)\. [A-Z]") + + +def check_prose(): + mds = [] + for d, dirs, fs in os.walk(ROOT): + dirs[:] = [x for x in dirs if x not in SKIP_DIRS] + mds += [os.path.join(d, f) for f in fs if f.endswith(".md")] + for path in sorted(mds): + rel = os.path.relpath(path, ROOT) + fence = False + for i, ln in enumerate(open(path, encoding="utf-8"), 1): + if ln.startswith("```"): + fence = not fence + continue + if fence: + continue + text = re.sub(r"`[^`]*`", "``", ln) + m = UK.search(text) + ok("prose", not m, "%s:%d: UK spelling %r" % (rel, i, m.group(0) if m else "")) + if not text.lstrip().startswith("|"): + body = ABBREV.sub("", re.sub(r"^\s*(#+\s+)?([0-9]+(\.[0-9]+)*\.?\s+)?(\*\*[^*]+\*\*\s*)?", "", text)) + ok("prose", not SENTENCE_BREAK.search(body), "%s:%d: one sentence per line" % (rel, i)) + + +def _slug(heading): + """A heading's anchor, as GitHub, Gitea and Forgejo compute it.""" + t = re.sub(r"[`*]", "", heading.strip().lower()) + t = "".join(ch for ch in t if ch.isalnum() or ch in " -_") + return t.replace(" ", "-") + + +def check_links(): + anchors = {} + mds = [] + for d, dirs, fs in os.walk(ROOT): + dirs[:] = [x for x in dirs if x not in SKIP_DIRS] + mds += [os.path.join(d, f) for f in fs if f.endswith(".md")] + for path in mds: + seen, fence = {}, False + for ln in open(path, encoding="utf-8"): + if ln.startswith("```"): + fence = not fence + elif not fence and ln.startswith("#"): + base = _slug(ln.lstrip("#")) + n = seen.get(base, 0) + seen[base] = n + 1 + anchors.setdefault(path, set()).add(base if n == 0 else "%s-%d" % (base, n)) + for path in sorted(mds): + fence = False + for i, ln in enumerate(open(path, encoding="utf-8"), 1): + if ln.startswith("```"): + fence = not fence + continue + if fence: + continue + for target in re.findall(r"\]\(([^)\s]+)\)", re.sub(r"`[^`]*`", "", ln)): + if re.match(r"^[a-z]+:", target): + continue + file, _, frag = target.partition("#") + dest = os.path.normpath(os.path.join(os.path.dirname(path), file)) if file else path + rel = os.path.relpath(path, ROOT) + ok("links", os.path.exists(dest), "%s:%d: no such file %s" % (rel, i, file)) + if frag and dest.endswith(".md") and os.path.exists(dest): + ok("links", frag in anchors.get(dest, ()), "%s:%d: no heading #%s in %s" % (rel, i, frag, file or "this file")) + + +WORD_NUMBERS = {w: i for i, w in enumerate( + "zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen " + "seventeen eighteen nineteen twenty".split())} +WORD_NUMBERS.update({"twenty-" + w: 20 + i for i, w in enumerate("one two three four five six seven eight nine".split(), 1)}) +# A count: digits or a number word, not the tail of a section number such as "22.3". +NUM = r"(?<![\d.])\b(\d+|[a-z]+(?:-[a-z]+)?)" +# What the prose may say about the repository, and the count it must equal. The text is lower-cased first. +COUNT_PATTERNS = [ + (r"\b(?:of the|lists|defines|has) " + NUM + r" formats\b", "formats"), + (NUM + r" (?:formats )?(?:are |of them |of the \d+ formats are )?`?candidate`?\b", "candidate"), + (NUM + r" (?:formats )?(?:are )?`?provisional`?\b", "provisional"), + (NUM + r" (?:json (?:\([^)]*\) )?)?schema(?:s| files)\b", "schemas"), + (NUM + r" (?:files of test vectors|vector files)\b", "vectors"), + (r"\ball " + NUM + r" files\b", "vectors"), + (NUM + r" (?:are )?(?:deliberately broken|broken packages|invalid ones|broken ones|invalid packages)\b", "invalid"), + (NUM + r" valid (?:example |fixture )?packages\b", "valid"), + (NUM + r" chapters\b", "chapters"), + (NUM + r" cases in all\b", "cases"), +] +# Where the prose names the specification's own version; other standards' versions are not checked. +VERSION_PATTERN = r"\b(?:paperspec|the formats are|the specification is at|this is|it is|is at|at) version (\d+\.\d+\.\d+)\b|\bpaperspec (\d+\.\d+\.\d+)\b" + + +def check_counts(): + """Every count and version the prose states about the repository equals what the repository holds.""" + formats = js(p("registry", "formats.json")) + rules = js(p("registry", "rules.json")) + vec = sorted(f for f in os.listdir(p("vectors")) if f.endswith(".jsonl")) + have = { + "formats": len(formats["formats"]), + "candidate": sum(f["status"] == "candidate" for f in formats["formats"]), + "provisional": sum(f["status"] == "provisional" for f in formats["formats"]), + "schemas": len(SCHEMA_FILES), + "vectors": len(vec), + "cases": sum(len(jl(p("vectors", f))) for f in vec), + "invalid": len(os.listdir(p("fixtures", "invalid"))), + "valid": sum(os.path.isdir(os.path.join(p("fixtures", "packages"), d)) for d in os.listdir(p("fixtures", "packages"))), + "chapters": len([f for f in os.listdir(p("spec")) if re.match(r"\d\d-.*\.md$", f)]), + } + top = re.search(r"^## (\S+)", open(p("CHANGELOG.md"), encoding="utf-8").read(), re.M).group(1) + pixi = re.search(r'^version = "([^"]+)"', open(p("pixi.toml"), encoding="utf-8").read(), re.M).group(1) + from tools.build import VERSION + ok("counts", top == pixi == formats["version"] == rules["version"] == VERSION, + "versions differ: CHANGELOG %s, pixi.toml %s, formats %s, rules %s, build.py %s" + % (top, pixi, formats["version"], rules["version"], VERSION)) + mds = [] + for d, dirs, fs in os.walk(ROOT): + dirs[:] = [x for x in dirs if x not in SKIP_DIRS] + mds += [os.path.join(d, f) for f in fs if f.endswith(".md")] + for path in sorted(mds): + rel = os.path.relpath(path, ROOT) + fence = False + for i, ln in enumerate(open(path, encoding="utf-8"), 1): + if ln.startswith("```"): + fence = not fence + continue + if fence: + continue + text = ln.lower() + for m in re.finditer(VERSION_PATTERN, text): + v = m.group(1) or m.group(2) + ok("counts", v == top, "%s:%d: version %s is not %s" % (rel, i, v, top)) + for pattern, what in COUNT_PATTERNS: + for m in re.finditer(pattern, text): + word = m.group(1) + if word.isdigit(): + n = int(word) + elif word in WORD_NUMBERS: + n = WORD_NUMBERS[word] + else: + continue + ok("counts", n == have[what], "%s:%d: says %s %s, the repository has %d" + % (rel, i, word, what, have[what])) + + +def check_log(): + """The log fixture (spec/23): its tiles hold the example's receipts and roster, its checkpoint is signed by the + team and cosigned by the witness, the project accepts it, and a checkpoint short of witnesses is refused.""" + R = p("fixtures", "records") + roster = {k["id"]: k for k in js(os.path.join(R, "roster.json"))["keys"]} + log_dir = os.path.join(R, "log") + entries, note = LG.read_log(log_dir) + receipts = jl(p("fixtures", "packages", HALE, "receipts.jsonl")) + want = [LG.entry(r) for r in receipts] + [LG.entry(js(os.path.join(R, "roster.json")))] + ok("log", entries == want, "the entries tiles do not hold the example's receipts and roster in order") + parsed, verified = LG.verify_checkpoint(note, roster) + ok("log", parsed and parsed["root"] == LG.root(entries) and parsed["size"] == len(entries), "checkpoint root or size") + ok("log", verified == ["ana", "wit"], "the checkpoint is not signed by the team and the witness: %s" % verified) + for path, data in LG.tiles(entries).items(): + full = os.path.join(log_dir, *path.split("/")) + ok("log", os.path.exists(full) and open(full, "rb").read() == data, "tile %s differs" % path) + ok("log", LG.tile_path(0, 1234067) == "tile/0/x001/x234/067" and LG.tile_path("entries", 5, 9) == "tile/entries/005.p/9", + "tile paths are not encoded as transparency logs share them") + settings = js(os.path.join(R, "project.json"))["settings"]["log"] + ok("log", LG.accept_checkpoint(note, roster, settings) == (True, []), "the project does not accept its checkpoint") + ok("log", not LG.accept_checkpoint(note, roster, dict(settings, threshold=2))[0], "two witnesses were not required") + ok("log", not LG.accept_checkpoint(note, roster, dict(settings, origin="other"))[0], "another origin was accepted") + alone = LG.sign_checkpoint(settings["origin"], entries, [("wit", __import__("tools.build", fromlist=["secret"]).secret("wit"))]) + ok("log", not LG.accept_checkpoint(alone, roster, settings)[0], "a checkpoint without the team's key was accepted") + # The ML-DSA-65 receipt verifies under dana's key, and fails under a tampered payload. + rec = js(os.path.join(R, "receipt-ml-dsa.json")) + ok("log", rec["signature"]["scheme"] == "ml-dsa-65" and RC.verify_signature(rec, roster), "the ML-DSA receipt does not verify") + ok("log", not RC.verify_signature(dict(rec, at="2026-10-13T09:00:01Z"), roster), "a changed ML-DSA receipt verifies") + ok("log", RC.receipt_status(rec, receipts + [rec], roster) == "valid", "the ML-DSA receipt is not valid") + for k in roster.values(): + ok("log", crypto.did_key(k["scheme"], base64.b64decode(k["public"])) == k["did"], "did of %s" % k["id"]) + + +def check_doc_values(): + """Every node ID, record ID or 64-hex hash the prose quotes exists in the fixtures or vectors, so the guides + never describe a fixture that no longer reads that way.""" + corpus = [] + for sub in ("fixtures", "vectors"): + for d, _, fs in os.walk(p(sub)): + for f in fs: + if f.endswith((".json", ".jsonl", ".csv", ".hex")): + with open(os.path.join(d, f), encoding="utf-8", errors="ignore") as fh: + corpus.append(fh.read()) + corpus = "\n".join(corpus) + ids_in_corpus = set(re.findall(r"[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}", corpus)) + hashes = set(re.findall(r"[0-9a-f]{64}", corpus)) + mds = [] + for d, dirs, fs in os.walk(ROOT): + dirs[:] = [x for x in dirs if x not in SKIP_DIRS] + mds += [os.path.join(d, f) for f in fs if f.endswith(".md")] + for path in sorted(mds): + rel = os.path.relpath(path, ROOT) + fence = False + for i, ln in enumerate(open(path, encoding="utf-8"), 1): + if ln.startswith("```"): + fence = not fence + continue + for h in set(re.findall(r"\b[0-9a-f]{64}\b", ln)): + ok("docs", h in hashes, "%s:%d: the hash %s… is in no fixture or vector" % (rel, i, h[:12])) + # IDs quoted in code spans or after a `#` in an address. + for m in re.finditer(r"`([a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6}|[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{12})`|#([a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6})\b", ln): + nid = m.group(1) or m.group(2) + if m.group(1) and not any(ch.isdigit() for ch in nid): + continue # a plain word of seven letters, such as `pattern`, is not an ID + ok("docs", nid in ids_in_corpus, "%s:%d: the ID %s is in no fixture or vector" % (rel, i, nid)) + + +def check_site(): + """The website builds, every Markdown file has a page, every internal link and fragment resolves, no Markdown + is left unrendered, and the namespace addresses the formats name are files the site serves.""" + from html.parser import HTMLParser + from tools import site + + class Page(HTMLParser): + def __init__(self): + super().__init__(convert_charrefs=True) + self.ids, self.links, self.text, self.skip = set(), [], [], 0 + + def handle_starttag(self, tag, attrs): + a = dict(attrs) + if "id" in a: + self.ids.add(a["id"]) + for k in ("href", "src"): + if a.get(k): + self.links.append(a[k]) + if tag in ("code", "pre", "script", "style"): + self.skip += 1 + + def handle_endtag(self, tag): + if tag in ("code", "pre", "script", "style"): + self.skip -= 1 + + def handle_data(self, data): + if not self.skip: + self.text.append(data) + + with tempfile.TemporaryDirectory() as tmp: + out = os.path.join(tmp, "site") + site.build(out) + pages = {} + for d, _, fs in os.walk(out): + for f in fs: + if f.endswith(".html"): + pg = Page() + with open(os.path.join(d, f), encoding="utf-8") as fh: + pg.feed(fh.read()) + pages[os.path.relpath(os.path.join(d, f), out)] = pg + for d, dirs, fs in os.walk(ROOT): + dirs[:] = [x for x in dirs if x not in SKIP_DIRS] + for f in fs: + if f.endswith(".md"): + md = os.path.relpath(os.path.join(d, f), ROOT) + ok("site", site.page_path(md) in pages, "%s has no page" % md) + for name, pg in sorted(pages.items()): + if name == "404.html": + continue + # Markdown syntax left in a single text node means a construct the renderer did not recognize. + bad = [m.group(0) for chunk in pg.text + for m in re.finditer(r"\]\(|\*\*|`|\n *(?:\||: |#{1,6} |[-*] |\d+\. )", chunk)] + ok("site", not bad, "%s: unrendered Markdown %r" % (name, sorted(set(bad))[:3])) + for link in pg.links: + if re.match(r"^[a-z][a-z0-9+.-]*:", link) or link.startswith("//"): + continue + path, _, frag = link.partition("#") + target = os.path.normpath(os.path.join(os.path.dirname(name), path)) if path else name + full = os.path.join(out, target) + if os.path.isdir(full): + target = os.path.join(target, "index.html") + full = os.path.join(out, target) + ok("site", os.path.exists(full), "%s: link to a missing file %s" % (name, link)) + if frag and target in pages: + ok("site", frag in pages[target].ids, "%s: no #%s in %s" % (name, frag, target)) + # The addresses the formats name are files of the site. + for f in SCHEMA_FILES: + sid = STORE.load(f)["$id"] + ok("site", sid.startswith(site.BASE_URL + "/") and + os.path.exists(os.path.join(out, sid[len(site.BASE_URL) + 1:])), "%s is not served at its $id" % f) + ctx_url = jl(os.path.join(p("fixtures", "records", "layer"), "annotations.jsonl"))[0]["@context"][1] + ok("site", ctx_url.startswith(site.BASE_URL + "/") and + os.path.exists(os.path.join(out, ctx_url[len(site.BASE_URL) + 1:])), "the context is not served at %s" % ctx_url) + vocab = js(p("context", "scienting-1.jsonld"))["@context"]["sct"] + ok("site", vocab == site.BASE_URL + "/vocab#", "the vocabulary IRI %s is not the site's vocab page" % vocab) + terms = [v if isinstance(v, str) else v["@id"] for k, v in js(p("context", "scienting-1.jsonld"))["@context"].items() + if not k.startswith("@")] + for t in terms: + if t.startswith("sct:"): + ok("site", t[4:] in pages["vocab/index.html"].ids, "the vocabulary page has no #%s" % t[4:]) + + +def main(): + import argparse + ap = argparse.ArgumentParser( + description="Check the whole repository: schemas, records, packages, zipped packages, broken packages, " + "vectors, a byte-for-byte rebuild, the SQL round trip and the bundle, counts, prose and links. " + "Exit status 0 means every check passed.") + ap.add_argument("--quick", action="store_true", help="skip the byte-for-byte rebuild, the slowest check") + args = ap.parse_args() + check_schemas() + check_registry() + check_records() + check_packages() + check_zips() + check_owner_revocation() + check_unsafe_paths() + check_incremental() + check_gate() + check_invalid() + check_vectors() + if not args.quick: + check_determinism() + check_sql() + check_counts() + check_prose() + check_links() + check_doc_values() + check_log() + check_site() + for k in sorted(COUNTS): + print("%-17s %5d checks" % (k, COUNTS[k])) + if FAILS: + print("\n%d failures:" % len(FAILS)) + for f in FAILS[:60]: + print(" " + f) + sys.exit(1) + print("\nAll checks pass.") + + +if __name__ == "__main__": + main() diff --git a/tools/load.py b/tools/load.py new file mode 100644 index 0000000..3e67f58 --- /dev/null +++ b/tools/load.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +"""Load packages into a SQLite database with the tables of sql/doc.sql and sql/store.sql. + +Non-normative tooling. +Usage: python3 tools/load.py --sqlite lab.db PACKAGE [PACKAGE ...] + python3 tools/load.py --sqlite lab.db --bundle --built-from REV PACKAGE [PACKAGE ...] +A package is a folder, or a zipped package (`.sct.zip`), unpacked under the rules of spec/12 §12.2 first. +With --bundle the new file is a scienting-bundle/1: it also gets the tables of sql/bundle-sqlite.sql, +the full-text search index and bundle_meta (spec/13 §13.5). +Each package is validated first, and nothing is loaded if any package fails. +Files without tables of their own (assets, datasets, derived files) are copied by SHA-256 into an +asset store folder beside the database, named <database>.assets/. +""" + +import argparse +import os +import sqlite3 +import sys +import tempfile + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, ROOT) + +from tools.oracle import db, package # noqa: E402 +from tools.oracle.schema import Store # noqa: E402 + + +def main(): + ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + ap.add_argument("--sqlite", required=True, help="the database file; created with the tables if new") + ap.add_argument("--bundle", action="store_true", help="build a new scienting-bundle/1 file with search") + ap.add_argument("--built-from", help="with --bundle: the store revision the packages come from") + ap.add_argument("--store", help="with --bundle: the store's name (default: the packages' common store)") + ap.add_argument("--max-size", metavar="BYTES", type=int, default=package.ZIP_LIMIT, + help="refuse a zipped package that expands past this many bytes (default %d)" % package.ZIP_LIMIT) + ap.add_argument("packages", nargs="+", help="package folders or zipped packages") + a = ap.parse_args() + if a.bundle and (os.path.exists(a.sqlite) or not a.built_from): + ap.error("--bundle needs --built-from and a database file that does not exist yet") + store, bad = Store(os.path.join(ROOT, "schemas")), False + with tempfile.TemporaryDirectory() as tmp: + folders = [] + for i, p in enumerate(a.packages): + if package.is_zip(p): + try: + folders.append(package.read_zip(p, os.path.join(tmp, str(i)), a.max_size)) + except package.Refusal as e: + print("%s: %s: %s" % (p, e.rule, e.message), file=sys.stderr) + bad = True + continue + else: + folders.append(p) + for e in package.validate(folders[-1], store).errors: + print("%s: %s: %s: %s" % (p, e["where"], e["rule"], e["message"]), file=sys.stderr) + bad = True + if bad: + sys.exit("Nothing was loaded.") + new = not os.path.exists(a.sqlite) + conn = sqlite3.connect(a.sqlite) + if a.bundle: + db.create_bundle(conn, os.path.join(ROOT, "sql")) + elif new: + db.create(conn, os.path.join(ROOT, "sql")) + for p in folders: + key = db.load(conn, p, a.sqlite + ".assets") + n = conn.execute("SELECT COUNT(*) FROM nodes WHERE doc_key = ?", (key,)).fetchone()[0] + if a.bundle: + print("%s: %d nodes, %d search rows" % (key, n, db.index(conn, key))) + else: + print("%s: %d nodes" % (key, n)) + if a.bundle: + stores = {r[0] for r in conn.execute("SELECT DISTINCT store FROM documents WHERE store IS NOT NULL")} + store_name = a.store or (stores.pop() if len(stores) == 1 else None) + if store_name is None: + sys.exit("The packages name no single store; give one with --store.") + db.write_meta(conn, store_name, a.built_from) + conn.commit() + + +if __name__ == "__main__": + main() diff --git a/tools/oracle/__init__.py b/tools/oracle/__init__.py new file mode 100644 index 0000000..9288a99 --- /dev/null +++ b/tools/oracle/__init__.py @@ -0,0 +1,13 @@ +"""The reference computations behind every expected value in this repository; see tools/README.md.""" + +import importlib.util +import sys + +if sys.version_info < (3, 14): + sys.exit("The paperspec tools need Python 3.14 or later; this is Python %d.%d." % sys.version_info[:2]) + +_missing = [m for m in ("cryptography", "jsonschema") if importlib.util.find_spec(m) is None] +if _missing: + sys.exit("The paperspec tools need %s %s; run them through pixi, or install %s with pip." + % ("the package" if len(_missing) == 1 else "the packages", " and ".join(_missing), + "it" if len(_missing) == 1 else "them")) diff --git a/tools/oracle/align.py b/tools/oracle/align.py new file mode 100644 index 0000000..9fae18d --- /dev/null +++ b/tools/oracle/align.py @@ -0,0 +1,127 @@ +"""Whole-document sentence alignment, in the manner of a patience diff. + +Non-normative; see spec/05-hashes.md, "Alignment". +Each reading is a list of items: {"id", "strict", "lossy", "complex", "container", "context"}. +""" + +import unicodedata + +from .hashing import prose_length + +MIN_PROSE = 20 + + +def _numeric_skeleton(strict): + keep = [] + i, n = 0, len(strict) + while i < n: + ch = strict[i] + if ch in "_^" and i + 1 < n and strict[i + 1] == "{": + keep.append(strict[i:i + 2]) + i += 2 + continue + if unicodedata.category(ch) == "Nd" or ch in "\u2212.,+}": + keep.append(ch) + i += 1 + return "".join(keep) + + +def classify(a, b): + """`None` when two paired sentences agree; else the suspect kind.""" + if a["strict"] == b["strict"] and a["complex"] == b["complex"]: + return None + if _numeric_skeleton(a["strict"]) != _numeric_skeleton(b["strict"]): + return "number" + if a["complex"] != b["complex"]: + return "equation" + return "word" + + +def _lis(pairs): + """Longest subsequence increasing in B among pairs sorted by A; lexicographically smallest A on ties.""" + n = len(pairs) + if not n: + return [] + best = [1] * n + nxt = [-1] * n + for i in range(n - 1, -1, -1): + for j in range(i + 1, n): + if pairs[j][1] > pairs[i][1] and best[j] + 1 > best[i]: + best[i] = best[j] + 1 + nxt[i] = j + top = max(best) + i = next(k for k in range(n) if best[k] == top) + out = [] + while i != -1: + out.append(pairs[i]) + i = nxt[i] + return out + + +def _lcs(A, B, a0, a1, b0, b1): + """LCS over align keys of A[a0:a1] and B[b0:b1], as index pairs, with the spec's tie rule.""" + n, m = a1 - a0, b1 - b0 + L = [[0] * (m + 1) for _ in range(n + 1)] + for i in range(n - 1, -1, -1): + for j in range(m - 1, -1, -1): + if A[a0 + i]["lossy"] == B[b0 + j]["lossy"]: + L[i][j] = L[i + 1][j + 1] + 1 + else: + L[i][j] = max(L[i + 1][j], L[i][j + 1]) + out = [] + i = j = 0 + while i < n and j < m: + if A[a0 + i]["lossy"] == B[b0 + j]["lossy"]: + out.append((a0 + i, b0 + j)) + i += 1 + j += 1 + elif L[i + 1][j] >= L[i][j + 1]: + i += 1 + else: + j += 1 + return out + + +def align(A, B): + """Align reading B to reading A. Returns {"pairs": [...], "suspects": [...]}.""" + count_a, count_b = {}, {} + for x in A: + count_a[x["lossy"]] = count_a.get(x["lossy"], 0) + 1 + for x in B: + count_b[x["lossy"]] = count_b.get(x["lossy"], 0) + 1 + pos_b = {x["lossy"]: j for j, x in enumerate(B)} + cands = [ + (i, pos_b[x["lossy"]]) for i, x in enumerate(A) + if count_a[x["lossy"]] == 1 and count_b.get(x["lossy"]) == 1 and prose_length(x["lossy"]) >= MIN_PROSE + ] + anchors = _lis(cands) + pairs = [] + prev_a, prev_b = 0, 0 + for ai, bi in anchors + [(len(A), len(B))]: + pairs += _lcs(A, B, prev_a, ai, prev_b, bi) + if ai < len(A): + pairs.append((ai, bi)) + prev_a, prev_b = ai + 1, bi + 1 + out_pairs, suspects = [], [] + for ai, bi in pairs: + kind = classify(A[ai], B[bi]) + out_pairs.append({"a": A[ai]["id"], "b": B[bi]["id"], "agree": kind is None}) + if kind: + suspects.append({"kind": kind, "a": A[ai]["id"], "b": B[bi]["id"]}) + if A[ai]["context"] != B[bi]["context"]: + suspects.append({"kind": "structure", "a": A[ai]["id"], "b": B[bi]["id"]}) + for (a1, b1), (a2, b2) in zip(pairs, pairs[1:]): + if a2 == a1 + 1 and b2 == b1 + 1: + same_a = A[a1]["container"] == A[a2]["container"] + same_b = B[b1]["container"] == B[b2]["container"] + if same_a != same_b: + suspects.append({"kind": "join", "a": A[a2]["id"], "b": B[b2]["id"]}) + paired_a = {a for a, _ in pairs} + paired_b = {b for _, b in pairs} + for i, x in enumerate(A): + if i not in paired_a: + suspects.append({"kind": "dropped", "a": x["id"], "b": None}) + for j, x in enumerate(B): + if j not in paired_b: + suspects.append({"kind": "added", "a": None, "b": x["id"]}) + return {"pairs": out_pairs, "suspects": suspects} diff --git a/tools/oracle/anchors.py b/tools/oracle/anchors.py new file mode 100644 index 0000000..3f8f930 --- /dev/null +++ b/tools/oracle/anchors.py @@ -0,0 +1,271 @@ +"""Addresses, anchors and their resolution. + +Non-normative; see spec/06-anchors.md. +""" + +import re +from fractions import Fraction + +from . import hashing, jcs +from .model import CONTAINERS_WITH_CONTENT, LEAVES, RUN_KINDS, Doc, anchor_class +from .text import norm + +ADDRESS_RE = re.compile( + r"^(?:(?P<store>[a-z0-9][a-z0-9._-]*)/)?" + r"(?P<key>[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(?:\.[a-z0-9][a-z0-9-]*)*)" + r"#(?P<node>[a-z0-9][a-z0-9._-]*)" + r"(?:@(?P<pin>[0-9a-f]{6}))?" + r"(?:\[(?P<start>0|[1-9][0-9]*):(?P<end>0|[1-9][0-9]*)\])?$" +) +QUOTE_CAP = 200 +CONTEXT_CAP = 32 + + +def parse_address(s): + m = ADDRESS_RE.match(s) + if not m: + return None + d = m.groupdict() + out = {"store": d["store"], "key": d["key"], "node": d["node"], "pin": d["pin"], "span": None} + if d["start"] is not None: + a, b = int(d["start"]), int(d["end"]) + if a > b: + return None + out["span"] = [a, b] + return out + + +def format_address(store, key, node, pin=None, span=None): + s = (store + "/" if store else "") + key + "#" + node + if pin: + s += "@" + pin[:6] + if span is not None: + s += "[%d:%d]" % tuple(span) + return s + + +def cell_context(doc, cell_id): + """Table label and the text of the row and column header paths of a cell.""" + cell = doc.nodes[cell_id] + row = doc.nodes[cell["parent"]] + table_id = doc.ancestors(cell_id)[-3] + table = doc.nodes[table_id] + cols = {c["id"]: c for c in table.get("attrs", {}).get("columns", [])} + col = cols.get(cell.get("attrs", {}).get("column"), {"header_path": []}) + + def txt(nid): + return norm(hashing.plain(doc, nid)) + + return { + "table_label": table.get("label"), + "row_path": [txt(x) for x in row.get("attrs", {}).get("header_path", [])], + "column_path": [txt(x) for x in col["header_path"]], + } + + +def make_anchor(doc, values, node, rev, span=None, store=None): + n = doc.nodes[node] + a = {"format": "scienting-anchor/1"} + if store: + a["store"] = store + a.update({"doc": doc.key, "node": node, "kind": n["kind"], "own_hash": values[node]["own_hash"], + "node_hash": values[node]["node_hash"]}) + if n["kind"] in LEAVES: + text = hashing.plain(doc, node) + if span is not None: + a["span"] = list(span) + exact = text[span[0]:span[1]] + pre, suf = text[max(0, span[0] - CONTEXT_CAP):span[0]], text[span[1]:span[1] + CONTEXT_CAP] + else: + exact, pre, suf = text, "", "" + q = {} + if len(exact) <= QUOTE_CAP: + q["exact"] = exact + else: + q["exact_hash"] = hashing.PLAIN(norm(exact)) + q["length"] = len(exact) + if pre: + q["prefix"] = pre + if suf: + q["suffix"] = suf + a["quote"] = q + if n["kind"] == "cell": + a["context"] = cell_context(doc, node) + elif anchor_class(n["kind"]) == "container-without-content": + a["leaves"] = [[x, values[x]["match_hash"]] for x in doc.leaves(node)] + a["rev"] = rev + return a + + +def _quote_hits(text, q): + """Start positions where the quote matches `text`.""" + if "exact" in q: + ex = q["exact"] + hits = [i for i in range(len(text) - len(ex) + 1) if text.startswith(ex, i)] + length = len(ex) + else: + length = q["length"] + hits = [i for i in range(len(text) - length + 1) + if hashing.PLAIN(norm(text[i:i + length])) == q["exact_hash"]] + if len(hits) > 1 and ("prefix" in q or "suffix" in q): + pre, suf = q.get("prefix", ""), q.get("suffix", "") + hits = [i for i in hits if text[:i].endswith(pre) and text[i + length:].startswith(suf)] + return hits, length + + +def _drift(state, doc, anchor, nid, threshold): + leaves = set(doc.leaves(nid)) + touched = set() + count = 0 + for c in state.corrections: + if c["index"] <= anchor["rev"]: + continue + inside = nid in (c.get("path") or []) or nid in (c.get("to_path") or []) + t = set(c.get("touched", [])) + if inside and t: + count += 1 + touched |= t + denom = len(leaves | touched) + share = Fraction(len(touched), denom) if denom else Fraction(0) + level = "none" if count == 0 else ("high" if share > threshold else "low") + return {"count": count, "share": _decimal(share), "level": level} + + +def _decimal(fr): + """A share as a decimal string with four places, rounded half up.""" + v = (fr * 10000 + Fraction(1, 2)).__floor__() + return "%d.%04d" % (v // 10000, v % 10000) + + +def _follow(state, nid): + """Follow aliases and retirements. Returns (live id or None, chain, via).""" + live = {n["id"] for n in state.nodes} + table = {e["id"]: e for e in state.ids} + chain, via = [], None + seen = set() + while nid not in live: + if nid in seen or nid not in table: + return None, chain, via + seen.add(nid) + e = table[nid] + if e["kind"] == "retired" or via is None: + via = e["kind"] + chain.append(nid) + nid = e.get("successor") + if nid is None: + return None, chain, via + return nid, chain, via + + +def _relabel_reverted_own(state, doc, nid, anchor): + """The own_hash the node had before the relabel corrections since the anchor, or None when anything else + changed the node or what is below it since (spec/06 §6.5: its *only* changes were relabel corrections).""" + since = [c for c in state.corrections if c["index"] > anchor["rev"] and ( + c.get("target") == nid or nid in (c.get("path") or []) or nid in (c.get("to_path") or []))] + rel = [c for c in since if c.get("target") == nid] + if not rel or any(c["op"] != "relabel" or c.get("target") != nid for c in since): + return None + n = dict(doc.nodes[nid], label=rel[0]["from"]) + tmp = Doc(doc.key, [n if x["id"] == nid else x for x in [doc.nodes[i] for i in doc.order]]) + return hashing.PLAIN(jcs.dumpb(hashing.own_content(tmp, nid, lambda h: hashing.PLAIN( + norm(hashing.plain(tmp, h)))))) + + +def resolve(state, anchor, threshold=Fraction(1, 4)): + doc = state.doc() + values = hashing.compute(doc) + kind = anchor.get("kind") + original = anchor["node"] + nid, chain, via = _follow(state, original) + live_kind = doc.nodes[nid]["kind"] if nid else None + table = {e["id"]: e for e in state.ids} + # The kind falls back to the retired entry the chain reached (spec/06 §6.5); an alias carries no kind. + retired_kind = next((table[x].get("node_kind") for x in reversed(chain) + if table.get(x, {}).get("kind") == "retired"), None) + kind = kind or live_kind or retired_kind + cls = anchor_class(kind) if kind else "leaf" + is_span = "span" in anchor + result = {"node": nid} + retired = via == "retired" + + def out(res, **kw): + r = {"result": res, "node": kw.pop("node", nid)} + if r["node"]: + r["node_hash"] = values[r["node"]]["node_hash"] + if chain: + r["via"] = chain + r.update(kw) + return r + + # The cell rule: a retired cell is found again by its table label and header paths. + def cell_rule(): + ctx = anchor.get("context") + q = anchor.get("quote") + if kind != "cell" or not ctx or not q: + return None + found = [] + for x in doc.order: + if doc.nodes[x]["kind"] != "cell": + continue + if cell_context(doc, x) != ctx: + continue + hits, ln = _quote_hits(hashing.plain(doc, x), q) + if len(hits) == 1: + found.append((x, hits[0], ln)) + if len(found) == 1: + x, i, ln = found[0] + kw = {"node": x} + if is_span: + kw["span"] = [i, i + ln] + return out("reattached", **kw) + return None + + if nid is None: + return cell_rule() or out("stale", node=None, reason="retired without a successor" if chain + else "unknown node") + + if cls == "leaf": + text = hashing.plain(doc, nid) + if not retired and values[nid]["node_hash"] == anchor["node_hash"]: + return out("current", **({"span": anchor["span"]} if is_span else {})) + q = anchor.get("quote") + if retired: + if q: + hits, ln = _quote_hits(text, q) + if (is_span and len(hits) == 1) or (not is_span and hits): + return out("moved", **({"span": [hits[0], hits[0] + ln]} if is_span else {})) + return cell_rule() or out("stale", reason="the successor does not contain the quote") + if q: + hits, ln = _quote_hits(text, q) + if len(hits) == 1: + return out("reattached", **({"span": [hits[0], hits[0] + ln]} if is_span else {})) + own = _relabel_reverted_own(state, doc, nid, anchor) + if own is not None and own == anchor["own_hash"]: + return out("reattached", reason="relabel") + return out("stale", reason="the node changed and the quote does not occur exactly once") + + if cls == "container-with-content": + if values[nid]["own_hash"] == anchor["own_hash"]: + if retired: + return out("moved") + if values[nid]["node_hash"] == anchor["node_hash"]: + return out("current") + return out("changed-below", drift=_drift(state, doc, anchor, nid, threshold)) + if not retired: + own = _relabel_reverted_own(state, doc, nid, anchor) + if own is not None and own == anchor["own_hash"]: + return out("reattached", reason="relabel") + return out("stale", reason="the node's own content changed") + + # Container without content. + if retired: + orig = anchor.get("leaves", []) + now = set(doc.leaves(nid)) + now_match = {values[x]["match_hash"] for x in now} + held = sum(1 for i, m in orig if i in now or m in now_match) + if 2 * held >= len(orig): + return out("moved") + return out("stale", reason="the successor holds fewer than half of the original leaves") + if values[nid]["node_hash"] == anchor["node_hash"]: + return out("current") + return out("changed-below", drift=_drift(state, doc, anchor, nid, threshold)) diff --git a/tools/oracle/corrections.py b/tools/oracle/corrections.py new file mode 100644 index 0000000..496abc5 --- /dev/null +++ b/tools/oracle/corrections.py @@ -0,0 +1,454 @@ +"""Corrections on an established document. + +Non-normative; see spec/11-corrections.md. +""" + +import copy + +from . import hashing +from .model import ATTRS, LABELLED, LEAVES, MATH_KINDS, RUN_KINDS, VERBATIM_KINDS, Doc, CHILDREN +from .tree import Refusal, canonical_runs, mint_ids, validate_references, validate_structure, _flatten +from . import jcs +from .schema import validate as schema_validate +from .text import digits, record_id, sha256_hex + +MERGEABLE = RUN_KINDS | {"paragraph", "list", "item", "quote", "caption", "figure-note", "table-note"} +SETTABLE = { + "section": {"level"}, + "table": {"columns"}, + "cell": {"column", "rowspan", "colspan", "role"}, + "row": {"header_path"}, + "list": {"ordered"}, + "item": {"marker"}, + "theorem": {"variant"}, +} +EDITABLE_RUN_FIELD = {"text": "text", "link": "text", "cite": "text", "xref": "text", "fnmark": "text", "math": "source"} + + +class State: + """The current state of a document: nodes, the ID table and the corrections applied.""" + + def __init__(self, key, nodes, ids=None, corrections=None, indexes=None): + self.key = key + self.nodes = [dict(n) for n in nodes] + self.ids = [dict(e) for e in (ids or [])] + self.corrections = [dict(c) for c in (corrections or [])] + self._indexes = dict(indexes or {}) + + @property + def rev(self): + return len(self.corrections) + + def doc(self): + return Doc(self.key, self.nodes) + + def index(self, hasher=hashing.PLAIN): + """The node values under `hasher`, kept with the state so the next correction rehashes only what changes.""" + if hasher.key not in self._indexes: + self._indexes[hasher.key] = hashing.Index.build(self.doc(), hasher) + return self._indexes[hasher.key] + + def used_ids(self): + return {n["id"] for n in self.nodes} | {e["id"] for e in self.ids} + + +def _strings(node): + """Editable strings of a leaf: (path, value) pairs.""" + k = node["kind"] + if k in RUN_KINDS: + out = [] + for i, r in enumerate(node["content"]): + f = EDITABLE_RUN_FIELD.get(r["kind"]) + if f: + out.append(((i, f), r[f])) + return out + if k in MATH_KINDS: + return [(("source",), node["content"]["source"])] + if k in VERBATIM_KINDS: + return [(("text",), node["content"]["text"])] + return [] + + +def _occurrences(s, find): + return [i for i in range(len(s) - len(find) + 1) if s.startswith(find, i)] + + +def _set_string(node, path, value): + if len(path) == 2: + i, f = path + node["content"][i] = dict(node["content"][i], **{f: value}) + else: + node["content"] = dict(node["content"], **{path[0]: value}) + + +def _has_crop(c): + return any(e.get("kind") == "crop" for e in c.get("evidence", [])) + + +def _rebuild(nodes): + """Recompute document order and `ord` from parent links, keeping sibling order as listed.""" + by_id = {n["id"]: n for n in nodes} + kids = {} + root = None + for n in nodes: + if n.get("parent") is None: + root = n["id"] + else: + kids.setdefault(n["parent"], []).append(n["id"]) + for p in kids: + kids[p].sort(key=lambda c: by_id[c]["ord"]) + out = [] + stack = [root] + while stack: + x = stack.pop() + out.append(by_id[x]) + for i, c in enumerate(kids.get(x, [])): + by_id[c]["ord"] = i + stack.extend(reversed(kids.get(x, []))) + return out + + +def _subtree(doc, nid): + return doc.preorder(nid) + + +def _place(nodes, nid, parent, after): + """Give `nid` a fractional position under `parent` after sibling `after` (None: first).""" + by_id = {n["id"]: n for n in nodes} + sibs = sorted([n for n in nodes if n.get("parent") == parent and n["id"] != nid], key=lambda n: n["ord"]) + for i, s in enumerate(sibs): + s["ord"] = 2 * i + 2 + if after is None: + pos = 0 + else: + if after not in by_id or by_id[after].get("parent") != parent: + raise Refusal("correction.target", "`place_after` is not a child of the parent") + pos = by_id[after]["ord"] + 1 + by_id[nid]["parent"] = parent + by_id[nid]["ord"] = pos + + +def gate(state, proposal, store, hasher=hashing.PLAIN): + """Run the gate (spec/11 §11.4) on a proposed correction, leaving `state` unchanged. + + Returns the state the correction would produce and the record it would append to corrections.jsonl, as apply + does. Raises Refusal naming the rule broken. `store` is the schema store that holds correction.schema.json. + """ + errors = schema_validate(store, "correction.schema.json", proposal) + if errors: + raise Refusal("correction.schema", "; ".join(errors[:3])) + return apply(state, proposal, hasher, store) + + +def _is_index(v): + return isinstance(v, int) and not isinstance(v, bool) and v >= 0 + + +def id_order(e): + """The order of ids.jsonl (spec/04 §4.4): aliases first by ID, then retirements by revision and ID.""" + return (0 if e["kind"] == "alias" else 1, e.get("rev", 0), e["id"]) + + +def _node_rule(error): + """The rule a node-schema error breaks, from the property the error names.""" + path = error.split(":", 1)[0] + for prefix, rule in (("/attrs", "doc.node.attrs"), ("/label", "doc.node.label"), ("/content", "doc.node.content")): + if path.startswith(prefix): + return rule + return "doc.node.schema" + + +def apply(state, c, hasher=hashing.PLAIN, store=None): + """Apply correction `c` to `state` and return the recorded correction. Raises Refusal. + + With a schema `store`, every node the correction changed or created is also validated against + node.schema.json, which is how the gate enforces the attribute shapes of spec/03 §3.4 (rule 11 of §11.4). + """ + c = copy.deepcopy(c) + doc = state.doc() + before_ix = state.index(hasher) + before_vals = before_ix.values + nodes = [copy.deepcopy(n) for n in state.nodes] + by_id = {n["id"]: n for n in nodes} + op = c["op"] + target = c.get("target") + if op != "insert" or "target" in c: + if target not in by_id: + raise Refusal("correction.target", "no live node %s" % target) + if target == doc.root and op in ("delete", "move", "merge", "reclassify"): + raise Refusal("correction.target", "the root cannot be " + op + "d") + record = {"format": "scienting-correction/1", "index": state.rev + 1} + retired, created = [], [] + path = doc.ancestors(target) if target in by_id else None + touched = [] + + if op == "replace": + node = by_id[target] + find, repl = c.get("find", ""), c["replace"] + if not find: + raise Refusal("correction.find", "find must not be empty") + hits = [] + for pth, s in _strings(node): + if "run" in c and (len(pth) != 2 or pth[0] != c["run"]): + continue + hits += [(pth, s, i) for i in _occurrences(s, find)] + if len(hits) != 1: + raise Refusal("correction.find", "find occurs %d times, not exactly once" % len(hits), target) + pth, s, i = hits[0] + if isinstance(repl, str): + _set_string(node, pth, s[:i] + repl + s[i + len(find):]) + else: + if len(pth) != 2 or node["content"][pth[0]]["kind"] != "text": + raise Refusal("correction.replace", "runs may replace text only inside a text run", target) + if any(r["kind"] == "equation" for r in repl): + raise Refusal("correction.replace", "equation runs are added by insert", target) + run = node["content"][pth[0]] + style = {"style": run["style"]} if "style" in run else {} + mid = [dict({"kind": "text", "text": s[:i]}, **style)] + list(repl) + [ + dict({"kind": "text", "text": s[i + len(find):]}, **style) + ] + node["content"] = node["content"][: pth[0]] + mid + node["content"][pth[0] + 1:] + if node["kind"] in RUN_KINDS: + node["content"] = canonical_runs(node["content"]) + touched = [target] + + elif op == "insert" and "node" in c: + if not _has_crop(c): + raise Refusal("correction.evidence", "an insert needs crop evidence") + parent = c["parent"] + if parent not in by_id: + raise Refusal("correction.target", "no live parent %s" % parent) + flat = [] + _flatten(copy.deepcopy(c["node"]), None, 0, flat) + new = mint_ids(state.key, flat, state.used_ids()) + new[0]["parent"] = parent + nodes.extend(new) + _place(nodes, new[0]["id"], parent, c.get("place_after")) + nodes = _rebuild(nodes) + created = [n["id"] for n in new] + tmp = Doc(state.key, nodes) + touched = [x for x in tmp.leaves(new[0]["id"])] + path = tmp.ancestors(new[0]["id"]) + target = new[0]["id"] + + elif op == "insert": + if not _has_crop(c): + raise Refusal("correction.evidence", "an insert needs crop evidence") + node = by_id[target] + if node["kind"] not in RUN_KINDS: + raise Refusal("correction.insert", "text is inserted into runs", target) + run, offset = c.get("run"), c.get("offset") + if not _is_index(run) or run >= len(node["content"]) or not _is_index(offset): + raise Refusal("correction.insert", "bad run or offset", target) + r = node["content"][run] + f = EDITABLE_RUN_FIELD.get(r["kind"]) + if not f or offset > len(r[f]) or not isinstance(c.get("text"), str): + raise Refusal("correction.insert", "bad run or offset", target) + node["content"][run] = dict(r, **{f: r[f][:offset] + c["text"] + r[f][offset:]}) + node["content"] = canonical_runs(node["content"]) + touched = [target] + + elif op == "delete": + gone = _subtree(doc, target) + touched = [x for x in gone if doc.nodes[x]["kind"] in LEAVES] + nodes = _rebuild([n for n in nodes if n["id"] not in set(gone)]) + retired = [(x, None) for x in gone] + + elif op == "split": + node = by_id[target] + if node["kind"] != "sentence": + raise Refusal("correction.split", "only sentences are split", target) + k = c.get("offset") + first, second, pos = [], [], 0 + total = len(hashing.plain_runs(node["content"], doc)) + if not _is_index(k) or not 0 < k < total: + raise Refusal("correction.split", "offset must fall inside the sentence", target) + for r in node["content"]: + ln = len(hashing.plain_runs([r], doc)) + if pos + ln <= k: + first.append(r) + elif pos >= k: + second.append(r) + elif r["kind"] == "text": + cut = k - pos + first.append(dict(r, text=r["text"][:cut])) + second.append(dict(r, text=r["text"][cut:])) + else: + raise Refusal("correction.split", "the offset falls inside a %s run" % r["kind"], target) + pos += ln + _strip_edge(first, end=True) + _strip_edge(second, end=False) + first, second = canonical_runs(first), canonical_runs(second) + if not first or not second: + raise Refusal("correction.split", "both parts must keep text", target) + new_spec = {"kind": "sentence", "content": second} + eq_second = [r["node"] for r in second if r["kind"] == "equation"] + flat = [dict(new_spec, _parent=None, ord=0)] + tmp_nodes = mint_ids(state.key, [dict(flat[0], content=[ + {"kind": "text", "text": hashing.plain_runs(second, doc)}])], state.used_ids()) + new_id = tmp_nodes[0]["id"] + node["content"] = first + new_node = {"id": new_id, "kind": "sentence", "parent": node["parent"], "ord": 0, "content": second} + if "fidelity" in node: + new_node["fidelity"] = node["fidelity"] + nodes.append(new_node) + _place(nodes, new_id, node["parent"], target) + for i, e in enumerate(eq_second): + by_id[e]["parent"] = new_id + by_id[e]["ord"] = i + nodes = _rebuild(nodes) + created = [new_id] + touched = [target, new_id] + + elif op == "merge": + other = c["with"] + node = by_id[target] + if other not in by_id: + raise Refusal("correction.target", "no live node %s" % other) + o = by_id[other] + if node["kind"] != o["kind"] or node["kind"] not in MERGEABLE: + raise Refusal("correction.merge", "merge joins two nodes of one mergeable kind", target) + if o.get("parent") != node.get("parent") or o["ord"] != node["ord"] + 1: + raise Refusal("correction.merge", "merge joins a node with its next sibling", target) + if node["kind"] in RUN_KINDS: + joiner = c.get("joiner", " ") + mid = [{"kind": "text", "text": joiner}] if joiner else [] + node["content"] = canonical_runs(node["content"] + mid + o["content"]) + touched = [target, other] + else: + touched = [x for x in doc.leaves(other) if x != other] + base = len(doc.kids(target)) + for i, kid in enumerate(doc.kids(other)): + by_id[kid]["parent"] = target + by_id[kid]["ord"] = base + i + nodes = _rebuild([n for n in nodes if n["id"] != other]) + retired = [(other, target)] + + elif op == "move": + parent = c["parent"] + if parent not in by_id or parent in set(_subtree(doc, target)) or c.get("place_after") == target: + raise Refusal("correction.move", "bad destination", target) + _place(nodes, target, parent, c.get("place_after")) + nodes = _rebuild(nodes) + touched = [x for x in doc.leaves(target)] + record["to_path"] = Doc(state.key, nodes).ancestors(target) + + elif op == "reclassify": + node = by_id[target] + new_kind = c["kind"] + old = node["kind"] + same_shape = (old in RUN_KINDS) == (new_kind in RUN_KINDS) and (old in MATH_KINDS) == ( + new_kind in MATH_KINDS) and (old in VERBATIM_KINDS) == (new_kind in VERBATIM_KINDS) + if new_kind not in CHILDREN or not same_shape: + raise Refusal("correction.reclassify", "%s cannot become %s" % (old, new_kind), target) + node["kind"] = new_kind + if new_kind not in LABELLED: + node.pop("label", None) + # Each kind carries only its own attributes (spec/03 §3.4). + kept = {k: v for k, v in node.get("attrs", {}).items() if k in ATTRS.get(new_kind, ())} + if kept: + node["attrs"] = kept + else: + node.pop("attrs", None) + record["from"] = old + touched = [x for x in doc.leaves(target)] + + elif op == "relabel": + node = by_id[target] + if node["kind"] not in LABELLED: + raise Refusal("correction.relabel", "%s takes no label" % node["kind"], target) + record["from"] = node.get("label") + if c.get("label") is None: + node.pop("label", None) # optional properties are omitted, never written as null (spec/03 §3.1) + else: + node["label"] = c["label"] + touched = [target] if node["kind"] in LEAVES else [] + + elif op == "set": + node = by_id[target] + attr = c["attr"] + if attr not in SETTABLE.get(node["kind"], ()): + raise Refusal("correction.set", "%s cannot be set on %s" % (attr, node["kind"]), target) + attrs = dict(node.get("attrs", {})) + record["from"] = attrs.get(attr) + attrs[attr] = c["value"] + node["attrs"] = attrs + touched = [target] if node["kind"] in LEAVES else [] + + else: + raise Refusal("correction.op", "unknown operation " + op) + + after_doc = Doc(state.key, nodes) + validate_structure(after_doc) + validate_references(after_doc) + after_ix = before_ix.update(after_doc) + after_vals = after_ix.values + if store is not None: + changed = {x for x in set(touched) | set(created) | {target} if x in after_doc.nodes} + for nid in sorted(changed): + errors = schema_validate(store, "node.schema.json", dict(after_doc.nodes[nid], **after_vals[nid])) + if errors: + raise Refusal(_node_rule(errors[0]), errors[0], nid) + + # Digits: a change to a digit needs crop evidence, and no leaf outside `touched` may change its digits. + needs_crop = False + if op == "replace": + rep = c["replace"] if isinstance(c["replace"], str) else hashing.plain_runs(c["replace"], doc) + needs_crop = digits(c["find"]) != digits(rep) + elif op == "delete": + needs_crop = any(digits(before_ix.plain(x)) for x in touched) + elif op == "relabel": + needs_crop = digits(record.get("from") or "") != digits(c.get("label") or "") + if needs_crop and not _has_crop(c): + raise Refusal("correction.digits", "a digit changed without crop evidence", target) + for nid in doc.leaves(doc.root): + if nid in after_ix.entries and nid not in touched: + if digits(before_ix.plain(nid)) != digits(after_ix.plain(nid)): + raise Refusal("correction.digits", "an undeclared digit change", nid) + + for k in ("op", "target", "find", "replace", "run", "offset", "text", "parent", "place_after", "node", "with", + "joiner", "kind", "label", "attr", "value", "evidence", "author", "reason", "at"): + if k in c: + record[k] = c[k] + if op == "insert" and "node" in c: + record["target"] = target + record["before"] = before_vals[target]["node_hash"] if target in before_vals else None + record["after"] = after_vals[target]["node_hash"] if target in after_vals else None + record["path"] = path + record["touched"] = sorted(set(touched)) + if created: + record["created"] = created + if retired: + record["retired"] = [r[0] for r in retired] + record["id"] = record_id(sha256_hex(jcs.dumpb({k: v for k, v in record.items() if k != "id"}))) + + old_kinds = {n["id"]: n["kind"] for n in state.nodes} + new_ids = list(state.ids) + for rid, succ in retired: + new_ids.append({"id": rid, "kind": "retired", "successor": succ, "node_kind": old_kinds[rid], + "rev": record["index"]}) + new_ids.sort(key=id_order) + new_state = State(state.key, [after_doc.nodes[x] for x in after_doc.preorder()], new_ids, + state.corrections + [record], {hasher.key: after_ix}) + return new_state, record + + +def _strip_edge(runs, end): + """Remove the whitespace at one edge of a split part, across as many text runs as it spans (spec/11 §11.1).""" + from .text import is_ws + while runs: + i = len(runs) - 1 if end else 0 + r = runs[i] + if r["kind"] != "text": + return + t = r["text"] + if end: + while t and is_ws(t[-1]): + t = t[:-1] + else: + while t and is_ws(t[0]): + t = t[1:] + if t: + runs[i] = dict(r, text=t) + return + del runs[i] diff --git a/tools/oracle/crypto.py b/tools/oracle/crypto.py new file mode 100644 index 0000000..aab1c3e --- /dev/null +++ b/tools/oracle/crypto.py @@ -0,0 +1,249 @@ +"""Keyed hashing, key derivation, Merkle roots and Ed25519. + +Non-normative; see spec/05-hashes.md and spec/08-fidelity.md. +HKDF and Ed25519 come from the `cryptography` package. +""" + +import hashlib + +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey +from cryptography.hazmat.primitives.kdf.hkdf import HKDF + +from . import jcs + + +def hkdf(ikm, salt, info, length=32): + """HKDF-SHA-256, RFC 5869.""" + return HKDF(algorithm=hashes.SHA256(), length=length, salt=salt, info=info).derive(ikm) + + +def team_key(secret): + return hkdf(secret, b"scienting-team-key/1", b"scienting-hash/1") + + +def key_id(key): + return hashlib.sha256(b"scienting-key-id/1" + key).hexdigest()[:16] + + +def page_hash(page_fp_hex): + return hashlib.sha256(b"scienting-page-hash/1" + bytes.fromhex(page_fp_hex)).hexdigest() + + +def page_key(page_fps_hex, context): + ikm = b"".join(bytes.fromhex(h) for h in page_fps_hex) + return hkdf(ikm, b"scienting-page-key/1", context.encode("utf-8")) + + +# --- Merkle trees (RFC 6962 hashing) ------------------------------------------ + + +def _leaf(data): + return hashlib.sha256(b"\x00" + data).digest() + + +def _node(left, right): + return hashlib.sha256(b"\x01" + left + right).digest() + + +def _mth(leaves): + n = len(leaves) + if n == 1: + return leaves[0] + k = 1 + while k * 2 < n: + k *= 2 + return _node(_mth(leaves[:k]), _mth(leaves[k:])) + + +def merkle_root(items): + """Root over receipt items: each item is a list such as ["node", id, hash].""" + if not items: + raise ValueError("a Merkle root needs at least one item") + return _mth([_leaf(jcs.dumpb(list(it))) for it in items]).hex() + + +def receipt_items(receipt): + items = [["node", nid, h] for nid, h in receipt.get("nodes", [])] + items += [list(r) for r in receipt.get("records", [])] + return items + + +EMPTY_ROOT = hashlib.sha256(b"").hexdigest() + + +def history_root(items): + """Root over an append-only history, with RFC 9162's hash of the empty list for no items.""" + if not items: + return EMPTY_ROOT + return _mth([_leaf(jcs.dumpb(list(it))) for it in items]).hex() + + +def leaf_hash(item): + return _leaf(jcs.dumpb(list(item))).hex() + + +# --- RFC 9162 proofs (§2.1.3 and §2.1.4) --------------------------------------- + + +def _path(m, leaves): + """PATH(m, D[n]): the inclusion path for the leaf at index m, as RFC 9162 §2.1.3.1 defines it.""" + n = len(leaves) + if n == 1: + return [] + k = 1 + while k * 2 < n: + k *= 2 + if m < k: + return _path(m, leaves[:k]) + [_mth(leaves[k:])] + return _path(m - k, leaves[k:]) + [_mth(leaves[:k])] + + +def inclusion_path(items, index): + """The audit path of `items[index]` in the tree over `items`, as hex hashes, leaf-most first.""" + if not 0 <= index < len(items): + raise ValueError("index outside the tree") + return [h.hex() for h in _path(index, [_leaf(jcs.dumpb(list(it))) for it in items])] + + +def verify_inclusion(root, leaf, index, size, path): + """Whether `path` proves that the leaf hash `leaf` is item `index` of a tree of `size` with `root` + (RFC 9162 §2.1.3.2). Never raises.""" + try: + if not 0 <= index < size: + return False + fn, sn = index, size - 1 + r = bytes.fromhex(leaf) + for p in path: + p = bytes.fromhex(p) + if sn == 0: + return False + if fn & 1 or fn == sn: + r = _node(p, r) + while fn & 1 == 0 and fn != 0: + fn >>= 1 + sn >>= 1 + else: + r = _node(r, p) + fn >>= 1 + sn >>= 1 + return sn == 0 and r.hex() == root + except (ValueError, TypeError): + return False + + +def _subproof(m, leaves, b): + n = len(leaves) + if m == n: + return [] if b else [_mth(leaves)] + k = 1 + while k * 2 < n: + k *= 2 + if m <= k: + return _subproof(m, leaves[:k], b) + [_mth(leaves[k:])] + return _subproof(m - k, leaves[k:], False) + [_mth(leaves[:k])] + + +def consistency_proof(items, m): + """PROOF(m, D[n]): what shows the tree over the first m items is a prefix of the tree over all n + (RFC 9162 §2.1.4.1), as hex hashes; empty when m is 0 or n.""" + n = len(items) + if not 0 <= m <= n: + raise ValueError("m outside the tree") + if m == 0 or m == n: + return [] + return [h.hex() for h in _subproof(m, [_leaf(jcs.dumpb(list(it))) for it in items], True)] + + +def verify_consistency(root_m, root_n, m, n, proof): + """Whether `proof` shows the tree of size m with `root_m` is a prefix of the tree of size n with `root_n` + (RFC 9162 §2.1.4.2). Never raises.""" + try: + if m == 0: + return not proof and root_m == EMPTY_ROOT + if m == n: + return not proof and root_m == root_n + if not 0 < m < n or not proof: + return False + proof = [bytes.fromhex(p) for p in proof] + fn, sn = m - 1, n - 1 + while fn & 1: + fn >>= 1 + sn >>= 1 + if fn == 0: + fr = sr = bytes.fromhex(root_m) + else: + fr = sr = proof[0] + proof = proof[1:] + for c in proof: + if sn == 0: + return False + if fn & 1 or fn == sn: + fr = _node(c, fr) + sr = _node(c, sr) + while fn & 1 == 0 and fn != 0: + fn >>= 1 + sn >>= 1 + else: + sr = _node(sr, c) + fn >>= 1 + sn >>= 1 + return sn == 0 and fr.hex() == root_m and sr.hex() == root_n + except (ValueError, TypeError): + return False + + +# --- Ed25519 (RFC 8032) ------------------------------------------------------- + + +def ed25519_public(secret): + """The 32-byte public key of a 32-byte Ed25519 secret.""" + return Ed25519PrivateKey.from_private_bytes(secret).public_key().public_bytes_raw() + + +def ed25519_sign(secret, msg): + return Ed25519PrivateKey.from_private_bytes(secret).sign(msg) + + +def ed25519_verify(public, msg, signature): + """True when `signature` is a valid Ed25519 signature of `msg` under `public`; never raises.""" + if len(public) != 32 or len(signature) != 64: + return False + try: + Ed25519PublicKey.from_public_bytes(public).verify(signature, msg) + except (InvalidSignature, ValueError): + return False + return True + + +# --- did:key (W3C did:key method, multicodec and base58btc) --------------------------- + +BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" +MULTICODEC = {"ed25519": 0xED, "ml-dsa-65": 0x1207} + + +def _varint(n): + out = bytearray() + while True: + b = n & 0x7F + n >>= 7 + out.append(b | (0x80 if n else 0)) + if not n: + return bytes(out) + + +def base58btc(data): + n = int.from_bytes(data, "big") + out = "" + while n: + n, r = divmod(n, 58) + out = BASE58[r] + out + return "1" * (len(data) - len(data.lstrip(b"\x00"))) + out + + +def did_key(scheme, public): + """The did:key of a public key: `z` and the base58btc of the multicodec prefix and the key bytes.""" + if scheme not in MULTICODEC: + raise ValueError("no multicodec code for " + scheme) + return "did:key:z" + base58btc(_varint(MULTICODEC[scheme]) + public) diff --git a/tools/oracle/db.py b/tools/oracle/db.py new file mode 100644 index 0000000..39f8fdd --- /dev/null +++ b/tools/oracle/db.py @@ -0,0 +1,319 @@ +"""The database form: loading a package into tables and unloading it again. + +Non-normative; see spec/13-database.md. +Loading is a pure function of the package, and unloading gives back the same bytes. +""" + +import json +import os +import shutil + +from . import hashing, jcs +from .model import Doc +from .package import SHA256_RE, _all_files, read_json, read_jsonl, safe_path, write +from .text import norm, sha256_hex +from .tree import Refusal + +SPEC_VERSION = "0.1.0" +BUNDLE_FORMAT = "scienting-bundle/1" + +STRUCTURED = {"MANIFEST.json", "document.json", "witnesses.json", "provenance.json", "roster.json", "nodes.jsonl", + "pages.jsonl", "locations.jsonl", "references.jsonl", "corrections.jsonl", "receipts.jsonl", + "ids.jsonl", "suspects.jsonl"} + + +def J(v): + return None if v is None else jcs.dumps(v) + + +def P(s): + return None if s is None else json.loads(s) + + +def B(v): + return None if v is None else (1 if v else 0) + + +def _opt(d, k, v): + if v is not None: + d[k] = v + + +def ins(conn, into, values): + conn.execute("INSERT %s VALUES (%s)" % (into, ",".join("?" * len(values))), values) + + +def create(conn, sql_dir): + for name in ("doc.sql", "store.sql"): + with open(os.path.join(sql_dir, name), encoding="utf-8") as f: + conn.executescript(f.read()) + + +def create_bundle(conn, sql_dir): + """The tables of a bundle: those of create(), then sql/bundle-sqlite.sql (spec/13 §13.5).""" + create(conn, sql_dir) + with open(os.path.join(sql_dir, "bundle-sqlite.sql"), encoding="utf-8") as f: + conn.executescript(f.read()) + + +def search_rows(key, nodes): + """The bundle's search rows for one document, in document order (spec/13 §13.5). + + One row per sentence, cell, equation outside a sentence and figure-text item, as + (doc_key, node, unit, context, text). For a node, `context` is the kind of its parent; a figure-text item + takes its panel as `node` and its `role` as `context`. Withheld nodes are skipped. + """ + doc = Doc(key, nodes) + out = [] + for nid in doc.order: + n = doc.nodes[nid] + kind = n["kind"] + parent = doc.nodes[n["parent"]]["kind"] if n.get("parent") else None + if n.get("withheld"): + continue + if kind in ("sentence", "cell") or (kind == "equation" and parent != "sentence"): + out.append((key, nid, kind, parent, norm(hashing.plain(doc, nid)))) + elif kind == "panel": + for item in (n.get("attrs") or {}).get("figure_text", []): + out.append((key, nid, "figure-text", item["role"], norm(item["text"]))) + return out + + +def index(conn, key): + """Fill the bundle's `search` table for the loaded document `key`.""" + nodes = [] + for n in _q(conn, "SELECT id, kind, parent, ord, attrs, content, withheld FROM nodes WHERE doc_key = ? ORDER BY seq", + (key,)): + rec = {"id": n["id"], "kind": n["kind"], "parent": n["parent"], "ord": n["ord"]} + _opt(rec, "attrs", P(n["attrs"])) + _opt(rec, "content", P(n["content"])) + if n["withheld"]: + rec["withheld"] = True + nodes.append(rec) + rows = search_rows(key, nodes) + conn.executemany("INSERT INTO search VALUES (?, ?, ?, ?, ?)", rows) + return len(rows) + + +def write_meta(conn, store, built_from, extra=None): + """Write `bundle_meta`: format, store, built_from and spec, then any `extra` pairs.""" + pairs = {"format": BUNDLE_FORMAT, "store": store, "built_from": built_from, "spec": SPEC_VERSION} + pairs.update(extra or {}) + conn.executemany("INSERT INTO bundle_meta VALUES (?, ?)", sorted(pairs.items())) + + +def load(conn, root, asset_store): + """Load the package at `root`. Files without tables go to `asset_store`, by SHA-256. + + Validate the package first (package.validate); this only refuses paths and hashes that are unsafe to use. + """ + _all_files(root) # refuses a symbolic link anywhere in the package before anything is copied + manifest = read_json(os.path.join(root, "MANIFEST.json")) + listed = {f["path"]: f for f in manifest["files"]} + for path, f in listed.items(): + if not safe_path(path): + raise Refusal("package.path.unsafe", "unsafe path %r" % path) + if not isinstance(f.get("sha256"), str) or not SHA256_RE.fullmatch(f["sha256"]): + raise Refusal("package.manifest.schema", "%s: sha256 is not 64 lowercase hex digits" % path) + + def jl(name): + return read_jsonl(os.path.join(root, name)) if name in listed else [] + + d = read_json(os.path.join(root, "document.json")) + key = d["key"] + with open(os.path.join(root, "MANIFEST.json"), "rb") as f: + package_hash = sha256_hex(f.read()) + prov = read_json(os.path.join(root, "provenance.json")) + roster = read_json(os.path.join(root, "roster.json")) if "roster.json" in listed else None + conn.execute("INSERT OR IGNORE INTO works VALUES (?, ?)", (d["work"]["key"], J(d["work"]["same_as"]))) + ins(conn, "INTO documents", (key, d.get("store"), J(d.get("aliases")), d["kind"], J(d["work"]), J(d["version"]), J(d["relations"]), + J(d["meta"]), d["language"], J(d.get("license")), d["policy"], J(d["hashing"]), d["root"], d["meta_hash"], + d["history"], + d["rev"], J(d["counts"]), J(d["fidelity"]), J(prov), J(roster), package_hash)) + for i, w in enumerate(read_json(os.path.join(root, "witnesses.json"))["witnesses"]): + ins(conn, "INTO witnesses", (key, w["id"], i, w["sha256"], w["size"], w["kind"], w["media_type"], w.get("pages"), + B(w.get("text_layer")), w.get("version_label"), J(w["origin"]), J(w["rights"]))) + for seq, n in enumerate(jl("nodes.jsonl")): + ins(conn, "INTO nodes", (key, n["id"], seq, n["kind"], n["parent"], n["ord"], n.get("label"), J(n.get("attrs")), + J(n.get("content")), B(n.get("withheld")), n.get("fidelity"), J(n.get("prov")), + n["text_hash"], n["match_hash"], n["align_key"], n["own_hash"], n["node_hash"])) + if isinstance(n.get("content"), list): + ords = 0 + for r in n["content"]: + if r["kind"] == "cite": + for ref in r["refs"]: + ins(conn, "OR IGNORE INTO citations", (key, n["id"], ref, ords)) + ords += 1 + for p in jl("pages.jsonl"): + ins(conn, "INTO pages", (key, p["witness"], p["page"], p["page_fp"], J(p["size"]), p.get("page_label"), + B(p["text_layer"]), J(p.get("stamps_removed")))) + for l in jl("locations.jsonl"): + ins(conn, "INTO locations", (key, l["node"], l["page_fp"], l["page"], l.get("page_label"), J(l["boxes"]), B(l.get("approx")))) + for r in jl("references.jsonl"): + ins(conn, "INTO refs", (key, r["node"], r.get("label"), J(r.get("csl")), J(r["resolution"]))) + main = ("format", "index", "id", "op", "target", "evidence", "author", "reason", "at", "before", "after", "path", + "touched") + for c in jl("corrections.jsonl"): + details = {k: v for k, v in c.items() if k not in main} + ins(conn, "INTO corrections", (key, c["index"], c["id"], c["op"], c.get("target"), J(c["evidence"]), J(c["author"]), + c["reason"], c["at"], c["before"], c["after"], J(c["path"]), J(c["touched"]), J(details))) + for e in jl("ids.jsonl"): + ins(conn, "INTO node_ids", (key, e["id"], e["kind"], e["successor"], e.get("node_kind"), e.get("rev"))) + for r in jl("receipts.jsonl"): + if r["format"] == "scienting-receipt/1": + ins(conn, "INTO receipts", (key, r["id"], r["level"], r["scope"], r["rev"], r["root"], J(r["nodes"]), + J(r.get("records")), J(r["evidence"]), r["by"], r["at"], J(r.get("qa")), + r.get("export_of"), J(r.get("keyed")), J(r["signature"]))) + for nid, h in r["nodes"]: + ins(conn, "INTO receipt_nodes", (r["id"], key, nid, h)) + else: + per = r.get("period") or {} + ins(conn, "INTO revocations", (key, r["id"], r.get("receipt"), r.get("signer"), per.get("from"), per.get("to"), + r["reason"], r["by"], r["at"], J(r["signature"]))) + for s in jl("suspects.jsonl"): + ins(conn, "INTO suspects", (key, s["id"], s["kind"], s.get("node"), J(s))) + os.makedirs(asset_store, exist_ok=True) + for path, f in listed.items(): + if path in STRUCTURED: + continue + present = f.get("present", True) + ins(conn, "INTO package_files", (key, path, f["sha256"], f["size"], 1 if present else 0)) + if present: + shutil.copyfile(os.path.join(root, path), os.path.join(asset_store, f["sha256"])) + return key + + +def _q(conn, sql, args): + cur = conn.execute(sql, args) + cols = [c[0] for c in cur.description] + return [dict(zip(cols, row)) for row in cur.fetchall()] + + +def unload(conn, key, out, asset_store): + """Write the package for `key` from the tables into `out`. Returns the package hash.""" + files = {} + d = _q(conn, "SELECT * FROM documents WHERE doc_key = ?", (key,))[0] + doc = {"format": "scienting-doc/1", "key": key} + _opt(doc, "store", d["store"]) + _opt(doc, "aliases", P(d["aliases"])) + doc.update({"kind": d["kind"], "work": P(d["work"]), "version": P(d["version"]), "relations": P(d["relations"]), + "meta": P(d["meta"]), "language": d["language"]}) + _opt(doc, "license", P(d["license"])) + doc.update({"policy": d["policy"], "hashing": P(d["hashing"]), "root": d["root_hash"], + "meta_hash": d["meta_hash"], "history": d["history"], "rev": d["rev"], "counts": P(d["counts"]), + "fidelity": P(d["fidelity"])}) + + def put(name, rec): + files[name] = (jcs.dumps(rec) + "\n").encode("utf-8") + + def putl(name, recs): + if recs: + files[name] = "".join(jcs.dumps(r) + "\n" for r in recs).encode("utf-8") + + put("document.json", doc) + put("provenance.json", P(d["provenance"])) + if d["roster"] is not None: + put("roster.json", P(d["roster"])) + ws = [] + for w in _q(conn, "SELECT * FROM witnesses WHERE doc_key = ? ORDER BY ord", (key,)): + rec = {"id": w["id"], "sha256": w["sha256"], "size": w["size"], "kind": w["kind"], "media_type": w["media_type"]} + _opt(rec, "pages", w["pages"]) + _opt(rec, "text_layer", None if w["text_layer"] is None else bool(w["text_layer"])) + _opt(rec, "version_label", w["version_label"]) + rec.update({"origin": P(w["origin"]), "rights": P(w["rights"])}) + ws.append(rec) + put("witnesses.json", {"witnesses": ws}) + nodes = [] + for n in _q(conn, "SELECT * FROM nodes WHERE doc_key = ? ORDER BY seq", (key,)): + rec = {"id": n["id"], "kind": n["kind"], "parent": n["parent"], "ord": n["ord"]} + _opt(rec, "label", n["label"]) + _opt(rec, "attrs", P(n["attrs"])) + _opt(rec, "content", P(n["content"])) + if n["withheld"]: + rec["withheld"] = True + _opt(rec, "fidelity", n["fidelity"]) + _opt(rec, "prov", P(n["prov"])) + for h in ("text_hash", "match_hash", "align_key", "own_hash", "node_hash"): + rec[h] = n[h] + nodes.append(rec) + putl("nodes.jsonl", nodes) + seq = {n["id"]: i for i, n in enumerate(nodes)} + pages = [] + for p in _q(conn, "SELECT * FROM pages WHERE doc_key = ? ORDER BY witness, page", (key,)): + rec = {"witness": p["witness"], "page": p["page"], "page_fp": p["page_fp"], "size": P(p["size"])} + _opt(rec, "page_label", p["page_label"]) + rec["text_layer"] = bool(p["text_layer"]) + _opt(rec, "stamps_removed", P(p["stamps_removed"])) + pages.append(rec) + putl("pages.jsonl", pages) + locs = [] + for l in _q(conn, "SELECT * FROM locations WHERE doc_key = ?", (key,)): + rec = {"node": l["node"], "page_fp": l["page_fp"], "page": l["page"]} + _opt(rec, "page_label", l["page_label"]) + rec["boxes"] = P(l["boxes"]) + if l["approx"]: + rec["approx"] = True + locs.append(rec) + locs.sort(key=lambda r: (seq[r["node"]], r["page"], r["page_fp"])) + putl("locations.jsonl", locs) + refs = [] + for r in _q(conn, "SELECT * FROM refs WHERE doc_key = ?", (key,)): + rec = {"node": r["node"]} + _opt(rec, "label", r["label"]) + _opt(rec, "csl", P(r["csl"])) + rec["resolution"] = P(r["resolution"]) + refs.append(rec) + refs.sort(key=lambda r: seq[r["node"]]) + putl("references.jsonl", refs) + cors = [] + for c in _q(conn, "SELECT * FROM corrections WHERE doc_key = ? ORDER BY idx", (key,)): + rec = {"format": "scienting-correction/1", "index": c["idx"], "id": c["id"], "op": c["op"]} + _opt(rec, "target", c["target"]) + rec.update({"evidence": P(c["evidence"]), "author": P(c["author"]), "reason": c["reason"], "at": c["made_at"], + "before": c["before_hash"], "after": c["after_hash"], "path": P(c["path"]), + "touched": P(c["touched"])}) + rec.update(P(c["details"])) + cors.append(rec) + putl("corrections.jsonl", cors) + ids = [] + for e in _q(conn, "SELECT * FROM node_ids WHERE doc_key = ?", (key,)): + rec = {"id": e["id"], "kind": e["kind"], "successor": e["successor"]} + _opt(rec, "node_kind", e["node_kind"]) + _opt(rec, "rev", e["rev"]) + ids.append(rec) + ids.sort(key=lambda e: (0 if e["kind"] == "alias" else 1, e.get("rev", 0), e["id"])) + putl("ids.jsonl", ids) + recs = [] + for r in _q(conn, "SELECT * FROM receipts WHERE doc_key = ?", (key,)): + rec = {"format": "scienting-receipt/1", "id": r["id"], "doc": key, "rev": r["rev"], "level": r["level"], + "scope": r["scope"], "nodes": P(r["nodes"])} + _opt(rec, "records", P(r["records"])) + rec.update({"root": r["root"], "evidence": P(r["evidence"]), "by": r["signer"], "at": r["made_at"]}) + _opt(rec, "qa", P(r["qa"])) + _opt(rec, "export_of", r["export_of"]) + _opt(rec, "keyed", P(r["keyed"])) + rec["signature"] = P(r["signature"]) + recs.append(rec) + for r in _q(conn, "SELECT * FROM revocations WHERE doc_key = ?", (key,)): + rec = {"format": "scienting-revocation/1", "id": r["id"]} + _opt(rec, "receipt", r["receipt"]) + _opt(rec, "signer", r["revoked_signer"]) + if r["period_from"] is not None: + rec["period"] = {"from": r["period_from"], "to": r["period_to"]} + rec.update({"reason": r["reason"], "by": r["signer"], "at": r["made_at"], "signature": P(r["signature"])}) + recs.append(rec) + recs.sort(key=lambda r: (r["at"], r["id"])) + putl("receipts.jsonl", recs) + sus = [P(s["record"]) for s in _q(conn, "SELECT * FROM suspects WHERE doc_key = ?", (key,))] + sus.sort(key=lambda s: s["id"]) + putl("suspects.jsonl", sus) + absent = [] + for f in _q(conn, "SELECT * FROM package_files WHERE doc_key = ?", (key,)): + if f["present"]: + if not SHA256_RE.fullmatch(f["sha256"]): + raise Refusal("package.manifest.schema", "%s: sha256 is not 64 lowercase hex digits" % f["path"]) + with open(os.path.join(asset_store, f["sha256"]), "rb") as fh: + files[f["path"]] = fh.read() + else: + absent.append({"path": f["path"], "sha256": f["sha256"], "size": f["size"], "present": False}) + return write(out, files, absent) diff --git a/tools/oracle/fingerprint.py b/tools/oracle/fingerprint.py new file mode 100644 index 0000000..d7b7ce1 --- /dev/null +++ b/tools/oracle/fingerprint.py @@ -0,0 +1,66 @@ +"""Page fingerprints, scienting-page/1, and download-stamp rules, scienting-stamps/1. + +Non-normative; see spec/07-geometry.md. +""" + +import math +import re +import unicodedata + +from . import jcs +from .notation import fold_plain_text +from .text import is_ws, norm, sha256_hex + + +def round_point(x): + """Round half up to a whole point.""" + return int(math.floor(x + 0.5)) + + +def _in_margin(box, size, margin): + x0, y0, x1, y1 = box + w, h = size + return x1 <= margin or x0 >= w - margin or y1 <= margin or y0 >= h - margin + + +def is_stamp(line, size, rules): + text = norm(line["text"]) + for r in rules: + if r.get("where", "any") == "margin": + if "box" not in line or not _in_margin(line["box"], size, r.get("margin", 36)): + continue + if re.search(r["pattern"], text, re.IGNORECASE | re.ASCII): + return r["id"] + return None + + +def _strip(s): + return "".join(c for c in s if not is_ws(c) and unicodedata.category(c) not in ("Cc", "Cf")) + + +def fp_text(text): + """Steps 3 and 4 of spec/07 §7.1: whitespace and control characters go first, so that "10 -20" and "10-20" + fold alike; then scripts and dashes fold as in the strict projection, then NFKC.""" + return _strip(unicodedata.normalize("NFKC", fold_plain_text(_strip(text)))) + + +def fingerprint(page, rules): + """`page`: {"size": [w, h], "lines": [{"text", "box"?}], "images": [sha256...]}. + + Returns (fingerprint, removed stamp rule IDs in line order). + """ + size = page["size"] + kept, removed = [], [] + for line in page.get("lines", []): + rid = is_stamp(line, size, rules) + if rid: + removed.append(rid) + else: + kept.append(line["text"]) + payload = { + "format": "scienting-page/1", + "size": [round_point(size[0]), round_point(size[1])], + "text": fp_text(" ".join(kept)), + "images": sorted(page.get("images", [])), + } + return sha256_hex(jcs.dumpb(payload)), removed diff --git a/tools/oracle/grade.py b/tools/oracle/grade.py new file mode 100644 index 0000000..42f972c --- /dev/null +++ b/tools/oracle/grade.py @@ -0,0 +1,93 @@ +"""Grading a scienting-submission/1 against a scienting-exercise/1 key. + +Non-normative; see spec/19-exercises.md. +""" + +from decimal import Decimal +from fractions import Fraction + +from . import anchors as A +from .tree import Refusal + + +def dec(d): + """A decimal string, exactly as the sum came out (spec/19 §19.4: points are decimal strings, summed exactly).""" + return format(Decimal(d), "f") + + +def _zero_like(d): + """Zero with the scale of `d`, so a missed element worth "0.5" scores "0.0".""" + return Decimal(0).quantize(Decimal(d)) + + +def _resolved(state, anchor): + r = A.resolve(state, anchor) + if r["result"] == "stale": + return None + return r["node"], r.get("span") + + +def _match(state, rule, student, key): + s, k = _resolved(state, student), _resolved(state, key) + if not s or not k or s[0] != k[0]: + return False + if rule.get("match") == "overlap" and k[1] is not None: + if s[1] is None: + return True + lo, hi = max(s[1][0], k[1][0]), min(s[1][1], k[1][1]) + size = k[1][1] - k[1][0] + return size > 0 and Fraction(max(0, hi - lo), size) >= Fraction(rule.get("min_overlap", "0.5")) + return True + + +def _any(state, rule, students, keys): + return any(_match(state, rule, s, k) for s in students for k in keys) + + +def key_anchors(body): + key = body["key"] + out = [] + for el in key.get("elements", []) + key.get("chain", []) + key.get("errors", []): + out += el["anchors"] + return out + + +def grade(body, submission, state): + for a in key_anchors(body): + if A.resolve(state, a)["result"] == "stale": + raise Refusal("grade.key-stale", "an anchor in the key is stale") + kind, key, rule, ans = body["exercise"], body["key"], body.get("rule", {}), submission["answers"] + items = [] + + def item(name, pts, got, fb): + items.append({"element": name, "points": dec(pts if got else _zero_like(pts)), "max": dec(pts), "feedback": fb}) + + if kind in ("anchor", "check"): + if kind == "check": + v = key["verdict"] + ok = ans.get("verdict") == v["value"] + item("verdict", v["points"], ok, v.get("feedback", {}).get("hit" if ok else "miss", "")) + for i, el in enumerate(key["elements"]): + ok = _any(state, rule, ans.get("anchors", []), el["anchors"]) + item("element:%d" % i, el["points"], ok, el.get("feedback", {}).get("hit" if ok else "miss", "")) + elif kind == "trace": + chain = ans.get("chain", []) + for i, link in enumerate(key["chain"]): + ok = i < len(chain) and _any(state, rule, chain[i], link["anchors"]) + item("link:%d" % i, link["points"], ok, link.get("feedback", {}).get("hit" if ok else "miss", "")) + elif kind == "reproduce": + ok = abs(Decimal(ans["value"]) - Decimal(key["value"])) <= Decimal(key["tolerance"]) + item("value", key["points"], ok, key.get("feedback", {}).get("hit" if ok else "miss", "")) + elif kind == "verify": + flags = ans.get("flags", []) + for i, err in enumerate(key["errors"]): + hit = [f for f in flags if _any(state, rule, [f["anchor"]], err["anchors"])] + ok = any(f["verdict"] == err["verdict"] for f in hit) + fb = err.get("feedback", {}).get("hit" if ok else "miss", "") + item("error:%d" % i, err["points"], ok, fb) + else: + raise Refusal("grade.kind", "unknown exercise kind " + kind) + score = sum((Decimal(x["points"]) for x in items), Decimal(0)) + total = sum((Decimal(x["max"]) for x in items), Decimal(0)) + return {"format": "scienting-grade/1", "submission": submission["id"], "exercise": submission["exercise"], + "score": dec(score), "max": dec(total), "items": items} diff --git a/tools/oracle/hashing.py b/tools/oracle/hashing.py new file mode 100644 index 0000000..016ac87 --- /dev/null +++ b/tools/oracle/hashing.py @@ -0,0 +1,320 @@ +"""The plain, strict and lossy projections, and the five content values. + +Non-normative; see spec/05-hashes.md. +""" + +import hashlib +import hmac +import unicodedata + +from . import jcs +from .model import LABELLED, MATH_KINDS, RUN_KINDS, VERBATIM_KINDS +from .notation import complex_key, fold_math, fold_plain_text, fold_styled_script +from .text import collapse_ws, is_ws, norm, remove_ws, trim + +OBJ = "\ufffc" +MARK_OPEN = "\ufff9" +MARK_CLOSE = "\ufffb" + + +class Hasher: + """SHA-256, or HMAC-SHA-256 under a key: every content value uses the same function.""" + + def __init__(self, key=None): + self.key = key + + def __call__(self, data): + if isinstance(data, str): + data = data.encode("utf-8") + if self.key is None: + return hashlib.sha256(data).hexdigest() + return hmac.new(self.key, data, hashlib.sha256).hexdigest() + + +PLAIN = Hasher() + + +# --- runs -------------------------------------------------------------------- + + +def _eq_source(doc, run): + eq = doc.nodes[run["node"]] + return eq["content"]["source"], eq["content"]["notation"] + + +def plain_runs(runs, doc=None): + out = [] + for r in runs: + k = r["kind"] + if k in ("text", "link", "cite", "xref", "fnmark"): + out.append(r["text"]) + elif k == "math": + out.append("$" + r["source"] + "$") + elif k == "equation": + src, _ = _eq_source(doc, r) + out.append("$$" + src + "$$") + else: + raise ValueError("run kind " + k) + return "".join(out) + + +def _strict_math(notation, source, complexes): + folded = fold_math(notation, source) + if folded is None: + complexes.append(complex_key(notation, source)) + return OBJ + return folded + + +def _finish_strict(s): + s = unicodedata.normalize("NFKC", s) + return trim(collapse_ws(s)) + + +def strict_runs_raw(runs, doc, complexes): + out = [] + for r in runs: + k = r["kind"] + if k == "text": + st = r.get("style", []) + if "sup" in st: + out.append(fold_styled_script("^", r["text"])) + elif "sub" in st: + out.append(fold_styled_script("_", r["text"])) + else: + out.append(fold_plain_text(r["text"])) + elif k == "link": + out.append(fold_plain_text(r["text"])) + elif k == "math": + out.append(_strict_math(r["notation"], r["source"], complexes)) + elif k == "equation": + src, notation = _eq_source(doc, r) + out.append(_strict_math(notation, src, complexes)) + elif k in ("cite", "xref", "fnmark"): + out.append(MARK_OPEN + remove_ws(unicodedata.normalize("NFC", r["text"])) + MARK_CLOSE) + else: + raise ValueError("run kind " + k) + return "".join(out) + + +def lossy_from_strict(s): + out = [] + stack = [] + i, n = 0, len(s) + while i < n: + ch = s[i] + if ch in "_^" and i + 1 < n and s[i + 1] == "{": + stack.append("s") + i += 2 + continue + if ch == "{": + stack.append("t") + out.append(ch) + elif ch == "}": + if stack: + if stack.pop() == "t": + out.append(ch) + else: + out.append(ch) + elif ch == MARK_OPEN: + j = s.find(MARK_CLOSE, i) + i = n if j < 0 else j + 1 + continue + else: + out.append(ch) + i += 1 + t = unicodedata.normalize("NFKC", "".join(out).casefold()) + return "".join( + c for c in t if not is_ws(c) and unicodedata.category(c) != "Pd" and c != "\u00ad" + ) + + +def prose_length(lossy): + return sum(1 for c in lossy if c != OBJ) + + +# --- nodes ------------------------------------------------------------------- + + +def plain(doc, nid): + n = doc.nodes[nid] + k = n["kind"] + if k in RUN_KINDS: + return plain_runs(n["content"], doc) + if k in MATH_KINDS: + return "$$" + n["content"]["source"] + "$$" + if k in VERBATIM_KINDS: + return n["content"]["text"] + return " ".join(plain(doc, x) for x in doc.text_leaves(nid)) + + +def strict(doc, nid): + """The strict canonical projection and the node's complex math keys, in order.""" + n = doc.nodes[nid] + k = n["kind"] + complexes = [] + if k in RUN_KINDS: + s = strict_runs_raw(n["content"], doc, complexes) + elif k in MATH_KINDS: + s = _strict_math(n["content"]["notation"], n["content"]["source"], complexes) + elif k in VERBATIM_KINDS: + s = n["content"]["text"] + else: + parts = [] + for x in doc.text_leaves(nid): + p, c = strict(doc, x) + parts.append(p) + complexes.extend(c) + return _finish_strict(" ".join(parts)), complexes + return _finish_strict(s), complexes + + +def lossy(doc, nid): + return lossy_from_strict(strict(doc, nid)[0]) + + +def _runs_for_own(runs): + out = [] + for r in runs: + if r["kind"] == "equation": + out.append({"kind": "equation"}) + else: + out.append(r) + return out + + +def own_content(doc, nid, text_hash_of=None): + n = doc.nodes[nid] + k = n["kind"] + o = {"kind": k} + attrs = n.get("attrs", {}) + if k in LABELLED: + o["label"] = n.get("label") + if k in RUN_KINDS: + o["runs"] = _runs_for_own(n["content"]) + if k in MATH_KINDS: + o["notation"] = n["content"]["notation"] + o["source"] = n["content"]["source"] + if k in VERBATIM_KINDS: + o["language"] = n["content"].get("language") + o["text"] = n["content"]["text"] + if k == "section": + o["level"] = attrs["level"] + heads = [c for c in doc.kids(nid) if doc.nodes[c]["kind"] == "heading"] + o["heading"] = text_hash_of(heads[0]) if heads else None + if k == "table": + o["columns"] = attrs.get("columns", []) + if k == "cell": + o["column"] = attrs.get("column") + o["rowspan"] = attrs.get("rowspan", 1) + o["colspan"] = attrs.get("colspan", 1) + o["role"] = attrs.get("role", "data") + if k == "theorem": + o["variant"] = attrs.get("variant") + return o + + +class _Entry: + """One node's cached work: its five values, and the projections its parent joins.""" + + __slots__ = ("sig", "values", "plain", "joined_plain", "joined_strict", "complexes") + + def __init__(self, sig, values, plain, joined_plain, joined_strict, complexes): + self.sig = sig + self.values = values + self.plain = plain + # What this node gives a container's projections: its text leaves joined, or None when it has none. + self.joined_plain = joined_plain + self.joined_strict = joined_strict + self.complexes = complexes + + +def _sig(doc, nid): + """Everything a node's values depend on besides its children's values.""" + n = doc.nodes[nid] + return (n["kind"], n.get("label"), n.get("attrs"), n.get("content"), tuple(doc.kids(nid))) + + +class Index: + """The five values of every node of one document, kept so that a change rehashes only what it touched. + + A node's values depend only on its own subtree, so after a change only the nodes whose own record or + children changed, and their ancestors, are rehashed. A container's projections are its children's + cached projections joined, so no container walks its subtree again. + """ + + def __init__(self, hasher=PLAIN): + self.hasher = hasher + self.entries = {} + self.values = {} + + @classmethod + def build(cls, doc, hasher=PLAIN): + ix = cls(hasher) + ix._rehash(doc, set(doc.nodes)) + return ix + + def update(self, doc): + """A new Index for `doc`, a later state of this one's document; this Index is left unchanged.""" + ix = Index(self.hasher) + ix.entries = {nid: e for nid, e in self.entries.items() if nid in doc.nodes} + ix.values = {nid: v for nid, v in self.values.items() if nid in doc.nodes} + dirty = {nid for nid in doc.nodes if nid not in ix.entries or ix.entries[nid].sig != _sig(doc, nid)} + for nid in list(dirty): + p = doc.nodes[nid].get("parent") + while p is not None and p not in dirty: + dirty.add(p) + p = doc.nodes[p].get("parent") + ix._rehash(doc, dirty) + return ix + + def plain(self, nid): + """The node's plain projection.""" + return self.entries[nid].plain + + def _rehash(self, doc, dirty): + h = self.hasher + for nid in reversed(doc.preorder()): + if nid not in dirty: + continue + n = doc.nodes[nid] + k = n["kind"] + kids = doc.kids(nid) + if k in RUN_KINDS or k in MATH_KINDS or k in VERBATIM_KINDS: + p = plain(doc, nid) + st, cx = strict(doc, nid) + # An equation line is never a text leaf; a sentence's equations are part of its own runs. + joined = (None, None, []) if k == "equation-line" else (p, st, cx) + else: + ps, ss, cx = [], [], [] + for c in kids: + e = self.entries[c] + if e.joined_plain is not None: + ps.append(e.joined_plain) + ss.append(e.joined_strict) + cx.extend(e.complexes) + p = " ".join(ps) + st = _finish_strict(" ".join(ss)) + joined = (p, " ".join(ss), cx) if ps else (None, None, []) + own = h(jcs.dumpb(own_content(doc, nid, lambda x: self.values[x]["text_hash"]))) + self.values[nid] = { + "text_hash": h(norm(p)), + "match_hash": h(st), + "align_key": h(lossy_from_strict(st)), + "own_hash": own, + "node_hash": h(jcs.dumpb({"own": own, "children": [self.values[c]["node_hash"] for c in kids]})), + } + self.entries[nid] = _Entry(_sig(doc, nid), self.values[nid], p, *joined) + + +def compute(doc, hasher=PLAIN): + """The five content values of every node, bottom up. Returns {id: {...}}.""" + return Index.build(doc, hasher).values + + +def meta_object(document): + return {k: document.get(k) for k in ("work", "version", "relations", "meta", "language", "license")} + + +def meta_hash(document, hasher=PLAIN): + return hasher(jcs.dumpb(meta_object(document))) diff --git a/tools/oracle/jcs.py b/tools/oracle/jcs.py new file mode 100644 index 0000000..c4d394f --- /dev/null +++ b/tools/oracle/jcs.py @@ -0,0 +1,155 @@ +"""Canonical JSON, RFC 8785 (JSON Canonicalization Scheme). + +Non-normative. +The normative rule is spec/01-conventions.md. +Most values serialize through the standard library's C encoder, which escapes strings exactly as RFC 8785 does. +Values it would write differently take the exact path below: floats, integers beyond 2^53, and member names +outside the Basic Multilingual Plane, which RFC 8785 sorts by UTF-16 code units rather than by code points. +""" + +import json +import math + +_C = json.JSONEncoder(ensure_ascii=False, separators=(",", ":"), sort_keys=True, allow_nan=False) +_EXACT_INT = 2**53 + +_ESC = { + 0x08: "\\b", + 0x09: "\\t", + 0x0A: "\\n", + 0x0C: "\\f", + 0x0D: "\\r", + 0x22: '\\"', + 0x5C: "\\\\", +} + + +def _string(s): + out = ['"'] + for ch in s: + cp = ord(ch) + if 0xD800 <= cp <= 0xDFFF: + raise ValueError("lone surrogate in string") + if cp in _ESC: + out.append(_ESC[cp]) + elif cp < 0x20: + out.append("\\u%04x" % cp) + else: + out.append(ch) + out.append('"') + return "".join(out) + + +def _number(x): + """ECMAScript Number.prototype.toString, as RFC 8785 requires.""" + if isinstance(x, bool): + raise TypeError("bool is not a number") + if isinstance(x, int): + if abs(x) > 2**53: + raise ValueError("integer outside the IEEE 754 exact range") + return str(x) + if not math.isfinite(x): + raise ValueError("NaN and Infinity are not JSON") + if x == 0: + return "0" + if x < 0: + return "-" + _number(-x) + # Shortest round-trip digits, as ECMAScript requires. + r = repr(x) + if "e" in r or "E" in r: + mant, exp = r.lower().split("e") + exp = int(exp) + else: + mant, exp = r, 0 + if "." in mant: + ip, fp = mant.split(".") + else: + ip, fp = mant, "" + digits = (ip + fp).lstrip("0") + # Position of the decimal point relative to the start of `digits`. + lead_zeros = len(ip + fp) - len((ip + fp).lstrip("0")) + n = len(ip) - lead_zeros + exp + digits = digits.rstrip("0") or "0" + k = len(digits) + if k <= n <= 21: + return digits + "0" * (n - k) + if 0 < n <= 21: + return digits[:n] + "." + digits[n:] + if -6 < n <= 0: + return "0." + "0" * (-n) + digits + e = n - 1 + sign = "+" if e >= 0 else "-" + if k == 1: + return digits + "e" + sign + str(abs(e)) + return digits[0] + "." + digits[1:] + "e" + sign + str(abs(e)) + + +def _key(s): + # RFC 8785 sorts member names by their UTF-16 code units. + return s.encode("utf-16-be") + + +def _fast(v): + """True when the C encoder writes `v` exactly as RFC 8785 does.""" + t = type(v) + if t is str or v is None or t is bool: + return True + if t is int: + return -_EXACT_INT <= v <= _EXACT_INT + if t is dict: + for k, x in v.items(): + if type(k) is not str or (not k.isascii() and max(k) > "\uffff") or not _fast(x): + return False + return True + if t is list or t is tuple: + return all(_fast(x) for x in v) + return False + + +def dumps(value): + """Serialize `value` to canonical JSON text.""" + if _fast(value): + text = _C.encode(value) + if not text.isascii(): + try: + text.encode("utf-8") + except UnicodeEncodeError: + raise ValueError("lone surrogate in string") from None + return text + return _exact(value) + + +def _exact(value): + if value is None: + return "null" + if value is True: + return "true" + if value is False: + return "false" + if isinstance(value, str): + return _string(value) + if isinstance(value, (int, float)): + return _number(value) + if isinstance(value, (list, tuple)): + return "[" + ",".join(dumps(v) for v in value) + "]" + if isinstance(value, dict): + for k in value: + if not isinstance(k, str): + raise TypeError("object keys must be strings") + items = sorted(value.items(), key=lambda kv: _key(kv[0])) + return "{" + ",".join(_string(k) + ":" + dumps(v) for k, v in items) + "}" + raise TypeError("not JSON: %r" % type(value)) + + +def dumpb(value): + """Canonical JSON as UTF-8 bytes.""" + return dumps(value).encode("utf-8") + + +def loads_line(data): + """Parse one canonical JSON line of bytes, refusing a line that is not canonical.""" + import json as _json + value = _json.loads(data.decode("utf-8")) + if dumpb(value) != data: + raise ValueError("not canonical JSON") + return value diff --git a/tools/oracle/keys.py b/tools/oracle/keys.py new file mode 100644 index 0000000..9fcd17b --- /dev/null +++ b/tools/oracle/keys.py @@ -0,0 +1,161 @@ +"""Work and document keys: a Scholar-style citation key plus a short hash of the work's identity. + +Non-normative; see spec/02-model.md §2.4. +A work key looks like `vaswani2017attention-k3f9`. The first part is what Google Scholar would call the work; the +characters after the hyphen come from a hash of the work's identity, so two works Scholar would name alike never +share a key. A document key is the work key with a suffix for anything other than the version of record. +""" + +import hashlib +import re +import unicodedata + +from .text import ALPHABET + +SCHEME = "scienting-key/1" +SUFFIX_LENGTH = 4 +MAX_SUFFIX = 51 +IDENTIFIER_ORDER = ("doi", "arxiv", "isbn", "pmid", "pmcid", "openalex") +WORK_KEY_RE = re.compile(r"^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}$") +DOCUMENT_KEY_RE = re.compile(r"^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}(\.[a-z0-9][a-z0-9-]*)*$") +STOP_WORDS = frozenset("a an the of on in for to and or at by with from as into onto about toward towards via " + "is are be its it this that these those".split()) +NAME_SUFFIXES = frozenset(["jr", "sr", "ii", "iii", "iv", "v", "phd", "md"]) +_YEAR = re.compile(r"^\d{4}$") +_DOI_PREFIX = re.compile(r"^(?:doi:|https?://(?:dx\.|www\.)?doi\.org/)+", re.IGNORECASE) + + +def fold(text): + """Lower-case ASCII with accents removed: `Müller` gives `muller`.""" + raw = text if isinstance(text, str) else "" + return unicodedata.normalize("NFKD", raw).encode("ascii", "ignore").decode().lower() + + +def title_words(title): + """A title's words, folded, with apostrophes removed and other punctuation splitting.""" + t = re.sub(r"['’`]", "", fold(title)) + return re.findall(r"[a-z0-9]+", t) + + +def family_name(name): + """A best guess at the family name in a display name: the part before a comma, else the last word that is + not a suffix such as `Jr.` or `III`.""" + name = (name or "").strip() + if "," in name: + head, _, tail = name.partition(",") + if tail.strip().rstrip(".").lower() not in NAME_SUFFIXES or " " not in head.strip(): + return head.strip() + name = head + parts = name.split() + while len(parts) > 1 and parts[-1].rstrip(".").lower() in NAME_SUFFIXES: + parts.pop() + return parts[-1] if parts else "" + + +def first_family(meta): + """The first author's family name from a CSL-JSON item, as the key spells it, or `anon`.""" + authors = meta.get("author") or [] + if not authors: + return "anon" + a = authors[0] + name = a.get("family") or family_name(a.get("literal") or a.get("name") or "") + fam = re.sub(r"[^a-z]", "", fold(name)) + return fam or "anon" + + +def year_of(meta): + """The year of a CSL-JSON item's `issued` date, when it is a four-digit year, else the empty string.""" + parts = (meta.get("issued") or {}).get("date-parts") or [] + y = parts[0][0] if parts and parts[0] else None + s = str(y) if isinstance(y, int) and not isinstance(y, bool) else (y if isinstance(y, str) else "") + return s if _YEAR.match(s) else "" + + +def scholar_part(meta): + """Family name, year and the first title word that is not a stop word: `vaswani2017attention`.""" + word = next((w for w in title_words(meta.get("title")) if w not in STOP_WORDS), "") + return first_family(meta) + year_of(meta) + word + + +def norm_doi(value): + """A DOI in bare form with ASCII letters lower-cased (DOI Handbook 2.4).""" + s = _DOI_PREFIX.sub("", value.strip()).strip() + return s.translate(str.maketrans("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")) + + +def identity(same_as, meta): + """What the key's hash is computed over: the first identifier of IDENTIFIER_ORDER among `same_as`, else the + folded metadata `meta:<title words>|<year>|<family>`.""" + by_kind = {} + for s in same_as or []: + kind, _, value = s.partition(":") + by_kind.setdefault(kind, value) + for kind in IDENTIFIER_ORDER: + if kind in by_kind and by_kind[kind]: + value = norm_doi(by_kind[kind]) if kind == "doi" else by_kind[kind].strip() + return "%s:%s" % (kind, value) + return "meta:%s|%s|%s" % (" ".join(title_words(meta.get("title"))), year_of(meta), first_family(meta)) + + +def suffix(ident, length=SUFFIX_LENGTH): + """The leading 5 × `length` bits of SHA-256 of `scienting-key/1:` and the identity, in Crockford base32.""" + if not 1 <= length <= MAX_SUFFIX: + raise ValueError("a key suffix is 1 to %d characters" % MAX_SUFFIX) + digest = int.from_bytes(hashlib.sha256((SCHEME + ":" + ident).encode("utf-8")).digest(), "big") + bits = digest >> (256 - 5 * length) + return "".join(ALPHABET[(bits >> (5 * (length - 1 - i))) & 31] for i in range(length)) + + +def work_key(same_as, meta, length=SUFFIX_LENGTH): + return scholar_part(meta) + "-" + suffix(identity(same_as, meta), length) + + +def unique_work_key(same_as, meta, taken): + """The work key, lengthened by two characters at a time while another identity already holds it.""" + for length in range(SUFFIX_LENGTH, MAX_SUFFIX + 1, 2): + key = work_key(same_as, meta, length) + if key not in taken: + return key + raise ValueError("no free key for " + identity(same_as, meta)) + + +def version_suffix(version): + """The document key's suffix for a version: nothing for the version of record, `.si` for Supporting + Information, `.v2` for a preprint or draft with a sequence number, else the version type.""" + t = version.get("type") + if t == "version-of-record": + return "" + if t == "supplement": + return ".si" + seq = version.get("seq") + if t in ("preprint", "draft", "submitted", "accepted") and isinstance(seq, int): + return ".v%d" % seq + return "." + t + + +def document_key(wkey, version): + return wkey + version_suffix(version) + + +def split_key(dkey): + """A document key's work key and its suffix (with the leading dot, or empty).""" + m = WORK_KEY_RE.match(dkey.split(".", 1)[0]) if dkey else None + if not m or not DOCUMENT_KEY_RE.match(dkey): + raise ValueError("%r is not a document key" % dkey) + head, dot, tail = dkey.partition(".") + return head, (dot + tail if dot else "") + + +def suffix_of(wkey): + return wkey.rsplit("-", 1)[1] + + +def suffix_agrees(wkey, same_as, meta): + """Whether a stored work key's hash part is what the identity gives: always checked when the identity is an + identifier such as a DOI, which never changes; a metadata identity may have been corrected since, so it + is not held to the key.""" + ident = identity(same_as, meta) + if ident.startswith("meta:"): + return True + sfx = suffix_of(wkey) + return sfx == suffix(ident, len(sfx)) diff --git a/tools/oracle/log.py b/tools/oracle/log.py new file mode 100644 index 0000000..32b0fd3 --- /dev/null +++ b/tools/oracle/log.py @@ -0,0 +1,204 @@ +"""A team's transparency log of receipts, revocations and roster changes, and its signed checkpoints. + +Non-normative; see spec/23-log.md. +Entries are the items of an RFC 9162 tree (the same tree as receipts and the correction history), and a +checkpoint is a signed note in the format transparency logs share (C2SP `signed-note` and `tlog-checkpoint`): +an origin line, the tree size, the root hash in Base64, an empty line, and one signature line per signer. +""" + +import base64 +import hashlib +import os + +from . import crypto, jcs + +ALGORITHM_ED25519 = 0x01 +FORMAT = "scienting-checkpoint/1" + + +def entry(record): + """The log item for a signed record: its kind, its ID and its record hash.""" + kinds = {"scienting-receipt/1": "receipt", "scienting-revocation/1": "revocation", "scienting-roster/1": "roster"} + kind = kinds.get(record.get("format")) + if kind is None: + raise ValueError("only receipts, revocations and rosters are logged") + if kind == "roster": + return ["roster", record.get("store", ""), hashlib.sha256(jcs.dumpb(record)).hexdigest()] + body = {k: v for k, v in record.items() if k not in ("id", "signature")} + return [kind, record["id"], hashlib.sha256(jcs.dumpb(body)).hexdigest()] + + +def root(entries): + return crypto.history_root(entries) + + +def key_hash(name, public): + """The four-byte key ID of a signed-note signer: SHA-256 of the name, a newline, the algorithm byte and the + public key, truncated.""" + return hashlib.sha256(name.encode("utf-8") + b"\n" + bytes([ALGORITHM_ED25519]) + public).digest()[:4] + + +def _b64(text): + """Canonical standard Base64 only: the bytes, or None when the text is not exactly their encoding.""" + try: + raw = base64.b64decode(text, validate=True) + except (ValueError, TypeError): + return None + return raw if base64.b64encode(raw).decode("ascii") == text else None + + +def note_body(origin, size, root_hex): + return "%s\n%d\n%s\n" % (origin, size, base64.b64encode(bytes.fromhex(root_hex)).decode("ascii")) + + +def sign_checkpoint(origin, entries, signers): + """A checkpoint note over `entries`, signed by each (name, secret) in `signers`.""" + body = note_body(origin, len(entries), root(entries)) + lines = [] + for name, secret in signers: + public = crypto.ed25519_public(secret) + sig = crypto.ed25519_sign(secret, body.encode("utf-8")) + lines.append("— %s %s" % (name, base64.b64encode(key_hash(name, public) + sig).decode("ascii"))) + return body + "\n" + "".join(ln + "\n" for ln in lines) + + +def parse_checkpoint(text): + """The origin, size, root (hex) and [(name, key hash, signature)] of a note, or None when malformed.""" + try: + body, _, sigs = text.partition("\n\n") + origin, size, root_b64 = body.split("\n") + rt = _b64(root_b64) + if rt is None or len(rt) != 32 or not size.isdigit() or str(int(size)) != size or not origin: + return None + out = [] + for ln in sigs.splitlines(): + if not ln.startswith("— "): + return None + _, name, blob = ln.split(" ", 2) + raw = _b64(blob) + if raw is None or len(raw) != 68: + return None + out.append((name, raw[:4], raw[4:])) + return {"origin": origin, "size": int(size), "root": rt.hex(), "signatures": out} + except (ValueError, TypeError): + return None + + +def verify_checkpoint(text, roster): + """The signers of the note whose Ed25519 signatures verify under the roster's keys of those names. + + Returns (parsed note, [names verified]); the note is None when malformed. Never raises. + """ + note = parse_checkpoint(text) + if note is None: + return None, [] + body = note_body(note["origin"], note["size"], note["root"]).encode("utf-8") + verified = [] + for name, kh, sig in note["signatures"]: + key = roster.get(name) + if not key or key.get("scheme") != "ed25519": + continue + try: + public = base64.b64decode(key["public"], validate=True) + except (ValueError, TypeError): + continue + if key_hash(name, public) == kh and crypto.ed25519_verify(public, body, sig): + verified.append(name) + return note, verified + + +# --- acceptance (spec/23 §23.3) --------------------------------------------------------------------------- + + +def accept_checkpoint(text, roster, settings): + """Whether a checkpoint note is one the project accepts: its origin is the project's log, a team key with the + `sign` purpose and the role `owner` signed it, and at least `threshold` of the project's witnesses cosigned it. + + Returns (accepted, reasons); `settings` is the project's `log` setting. Never raises. + """ + note, verified = verify_checkpoint(text, roster) + reasons = [] + if note is None: + return False, ["the note is malformed"] + if note["origin"] != settings.get("origin"): + reasons.append("the origin is not the project's log") + team = [n for n in verified if roster[n].get("role") == "owner" and "sign" in roster[n].get("purposes", [])] + if not team: + reasons.append("no owner key with the sign purpose signed it") + witnesses = [n for n in verified if n in settings.get("witnesses", []) and "witness" in roster[n].get("purposes", [])] + if len(witnesses) < settings.get("threshold", 0): + reasons.append("%d of %d witnesses cosigned" % (len(witnesses), settings.get("threshold", 0))) + return not reasons, reasons + + +# --- tiles (spec/23 §23.4) -------------------------------------------------------------------------------- + +TILE_HEIGHT = 8 +TILE_WIDTH = 1 << TILE_HEIGHT + + +def tile_path(level, index, width=None): + """The path of a tile: `tile/<level>/<N>`, with N as 3-digit groups, all but the last prefixed `x`, and + `.p/<W>` for a partial tile of W entries; `level` is a number or `entries`.""" + parts, n = ["%03d" % (index % 1000)], index // 1000 + while n: + parts.insert(0, "x%03d" % (n % 1000)) + n //= 1000 + path = "tile/%s/%s" % (level, "/".join(parts)) + return path + (".p/%d" % width if width is not None else "") + + +def tiles(entries): + """Every tile of a log over `entries`, as {path: bytes}: hash tiles per level (32-byte hashes of the complete + subtrees of 256^level entries, 256 to a tile) and entries tiles (canonical JSON Lines, 256 to a tile).""" + out = {} + leaves = [crypto._leaf(jcs.dumpb(list(e))) for e in entries] + level = 0 + while True: + span = TILE_WIDTH ** level + nodes = [crypto._mth(leaves[i * span:(i + 1) * span]) for i in range(len(leaves) // span)] + if not nodes: + break + for t in range(len(nodes) // TILE_WIDTH): + out[tile_path(level, t)] = b"".join(nodes[t * TILE_WIDTH:(t + 1) * TILE_WIDTH]) + rest = len(nodes) % TILE_WIDTH + if rest: + out[tile_path(level, len(nodes) // TILE_WIDTH, rest)] = b"".join(nodes[-rest:]) + level += 1 + for t in range(len(entries) // TILE_WIDTH): + out[tile_path("entries", t)] = b"".join(jcs.dumps(list(e)).encode("utf-8") + b"\n" + for e in entries[t * TILE_WIDTH:(t + 1) * TILE_WIDTH]) + rest = len(entries) % TILE_WIDTH + if rest: + out[tile_path("entries", len(entries) // TILE_WIDTH, rest)] = b"".join( + jcs.dumps(list(e)).encode("utf-8") + b"\n" for e in entries[-rest:]) + return out + + +def write_log(entries, origin, signers, out_dir): + """Write a log as static files: `checkpoint` and every tile. Returns the checkpoint note.""" + note = sign_checkpoint(origin, entries, signers) + for path, data in tiles(entries).items(): + full = os.path.join(out_dir, *path.split("/")) + os.makedirs(os.path.dirname(full), exist_ok=True) + with open(full, "wb") as f: + f.write(data) + with open(os.path.join(out_dir, "checkpoint"), "w", encoding="utf-8") as f: + f.write(note) + return note + + +def read_log(log_dir): + """The entries and the checkpoint note of a log written by `write_log`, read from its entries tiles.""" + with open(os.path.join(log_dir, "checkpoint"), encoding="utf-8") as f: + note = f.read() + parsed = parse_checkpoint(note) + if parsed is None: + raise ValueError("the checkpoint is malformed") + size = parsed["size"] + entries = [] + for t in range(size // TILE_WIDTH + (1 if size % TILE_WIDTH else 0)): + width = size % TILE_WIDTH if (t + 1) * TILE_WIDTH > size else None + with open(os.path.join(log_dir, *tile_path("entries", t, width).split("/")), "rb") as f: + entries += [json_line for json_line in (jcs.loads_line(ln) for ln in f.read().split(b"\n") if ln)] + return entries, note diff --git a/tools/oracle/mldsa.py b/tools/oracle/mldsa.py new file mode 100644 index 0000000..a7baaaa --- /dev/null +++ b/tools/oracle/mldsa.py @@ -0,0 +1,446 @@ +"""ML-DSA-65, the module-lattice digital signature algorithm of FIPS 204, in plain Python. + +Non-normative; see spec/08-fidelity.md §8.4. +This is the reference form of the standard, slow and clear, for the signature scheme `ml-dsa-65`: key generation +from a 32-byte seed, the deterministic signing variant (the hedging bytes are zero), and verification. Keys and +signatures are the standard's byte encodings, so a production verifier can use any FIPS 204 library. The pure +(non pre-hashed) variant with an empty context is used, as the standard's ML-DSA.Sign defines it. +""" + +import hashlib + +Q = 8380417 +N = 256 +D = 13 +ZETA = 1753 +K, L = 6, 5 +ETA = 4 +TAU = 49 +LAMBDA = 192 +GAMMA1 = 1 << 19 +GAMMA2 = (Q - 1) // 32 +BETA = TAU * ETA +OMEGA = 55 +PK_SIZE = 32 + 32 * K * (23 - D) +SK_SIZE = 32 + 32 + 64 + 32 * ((L + K) * 4 + D * K) +SIG_SIZE = LAMBDA // 4 + L * 32 * 20 + OMEGA + K +F_INV256 = 8347681 # 256^-1 mod q + + +def _bitrev8(m): + return int("{:08b}".format(m)[::-1], 2) + + +ZETAS = [pow(ZETA, _bitrev8(m), Q) for m in range(256)] + + +def _shake256(data, n): + return hashlib.shake_256(data).digest(n) + + +def _shake128(data, n): + return hashlib.shake_128(data).digest(n) + + +# --- bit packing (FIPS 204 §7.1) ---------------------------------------------------------------------------- + + +def _bitlen(x): + return x.bit_length() + + +def simple_bit_pack(w, b): + """Coefficients in [0, b] as bitlen(b)-bit little-endian fields.""" + bits = _bitlen(b) + acc = 0 + for i, c in enumerate(w): + acc |= c << (bits * i) + return acc.to_bytes(32 * bits, "little") + + +def simple_bit_unpack(v, b): + bits = _bitlen(b) + acc = int.from_bytes(v, "little") + mask = (1 << bits) - 1 + return [(acc >> (bits * i)) & mask for i in range(N)] + + +def bit_pack(w, a, b): + """Coefficients in [-a, b] stored as b - w_i in bitlen(a + b) bits.""" + bits = _bitlen(a + b) + acc = 0 + for i, c in enumerate(w): + acc |= (b - c) << (bits * i) + return acc.to_bytes(32 * bits, "little") + + +def bit_unpack(v, a, b): + bits = _bitlen(a + b) + acc = int.from_bytes(v, "little") + mask = (1 << bits) - 1 + return [b - ((acc >> (bits * i)) & mask) for i in range(N)] + + +def hint_bit_pack(h): + y = bytearray(OMEGA + K) + index = 0 + for i in range(K): + for j in range(N): + if h[i][j]: + y[index] = j + index += 1 + y[OMEGA + i] = index + return bytes(y) + + +def hint_bit_unpack(y): + h = [[0] * N for _ in range(K)] + index = 0 + for i in range(K): + if y[OMEGA + i] < index or y[OMEGA + i] > OMEGA: + return None + first = index + while index < y[OMEGA + i]: + if index > first and y[index - 1] >= y[index]: + return None + h[i][y[index]] = 1 + index += 1 + if any(y[i] != 0 for i in range(index, OMEGA)): + return None + return h + + +# --- arithmetic --------------------------------------------------------------------------------------------- + + +def _mod_pm(r, m): + """r mod± m: the representative in (-m/2, m/2].""" + r %= m + return r - m if r > m // 2 else r + + +def power2round(r): + rp = r % Q + r0 = _mod_pm(rp, 1 << D) + return (rp - r0) >> D, r0 + + +def decompose(r): + rp = r % Q + r0 = _mod_pm(rp, 2 * GAMMA2) + if rp - r0 == Q - 1: + return 0, r0 - 1 + return (rp - r0) // (2 * GAMMA2), r0 + + +def high_bits(r): + return decompose(r)[0] + + +def low_bits(r): + return decompose(r)[1] + + +def make_hint(z, r): + return 1 if high_bits(r) != high_bits(r + z) else 0 + + +def use_hint(h, r): + m = (Q - 1) // (2 * GAMMA2) + r1, r0 = decompose(r) + if h and r0 > 0: + return (r1 + 1) % m + if h and r0 <= 0: + return (r1 - 1) % m + return r1 + + +def _inf_norm(w): + return max(abs(_mod_pm(c, Q)) for c in w) + + +def ntt(w): + w = list(w) + m, length = 0, 128 + while length >= 1: + start = 0 + while start < N: + m += 1 + z = ZETAS[m] + for j in range(start, start + length): + t = z * w[j + length] % Q + w[j + length] = (w[j] - t) % Q + w[j] = (w[j] + t) % Q + start += 2 * length + length //= 2 + return w + + +def ntt_inv(w): + w = list(w) + m, length = 256, 1 + while length < N: + start = 0 + while start < N: + m -= 1 + z = (-ZETAS[m]) % Q + for j in range(start, start + length): + t = w[j] + w[j] = (t + w[j + length]) % Q + w[j + length] = z * (t - w[j + length]) % Q + start += 2 * length + length *= 2 + return [c * F_INV256 % Q for c in w] + + +def _mul(a, b): + return [x * y % Q for x, y in zip(a, b)] + + +def _add(a, b): + return [(x + y) % Q for x, y in zip(a, b)] + + +def _sub(a, b): + return [(x - y) % Q for x, y in zip(a, b)] + + +# --- sampling (FIPS 204 §7.3) ------------------------------------------------------------------------------- + + +def _coeff_from_three_bytes(b0, b1, b2): + z = ((b2 & 0x7F) << 16) | (b1 << 8) | b0 + return z if z < Q else None + + +def rej_ntt_poly(rho): + out, j, n = [], 0, 3 * 300 + stream = _shake128(rho, n) + pos = 0 + while j < N: + if pos + 3 > len(stream): + n *= 2 + stream = _shake128(rho, n) + c = _coeff_from_three_bytes(stream[pos], stream[pos + 1], stream[pos + 2]) + pos += 3 + if c is not None: + out.append(c) + j += 1 + return out + + +def _coeff_from_half_byte(b): + return 4 - b if b < 9 else None # eta = 4 + + +def rej_bounded_poly(rho): + out, j, n = [], 0, 200 + stream = _shake256(rho, n) + pos = 0 + while j < N: + if pos >= len(stream): + n *= 2 + stream = _shake256(rho, n) + z = stream[pos] + pos += 1 + z0 = _coeff_from_half_byte(z & 15) + z1 = _coeff_from_half_byte(z >> 4) + if z0 is not None: + out.append(z0) + j += 1 + if z1 is not None and j < N: + out.append(z1) + j += 1 + return out + + +def expand_a(rho): + return [[rej_ntt_poly(rho + bytes([s, r])) for s in range(L)] for r in range(K)] + + +def expand_s(rho_prime): + s1 = [rej_bounded_poly(rho_prime + r.to_bytes(2, "little")) for r in range(L)] + s2 = [rej_bounded_poly(rho_prime + (r + L).to_bytes(2, "little")) for r in range(K)] + return s1, s2 + + +def expand_mask(rho, mu): + c = 1 + _bitlen(GAMMA1 - 1) + return [bit_unpack(_shake256(rho + (mu + r).to_bytes(2, "little"), 32 * c), GAMMA1 - 1, GAMMA1) for r in range(L)] + + +def sample_in_ball(rho): + c = [0] * N + n = 8 + TAU * 4 + stream = _shake256(rho, n) + signs = int.from_bytes(stream[:8], "little") + pos = 8 + for i in range(N - TAU, N): + while True: + if pos >= len(stream): + n *= 2 + stream = _shake256(rho, n) + j = stream[pos] + pos += 1 + if j <= i: + break + c[i] = c[j] + c[j] = 1 if (signs >> (i + TAU - N)) & 1 == 0 else Q - 1 + return c + + +# --- encodings (FIPS 204 §7.2) ------------------------------------------------------------------------------ + + +def pk_encode(rho, t1): + return rho + b"".join(simple_bit_pack(t, (1 << (23 - D)) - 1) for t in t1) + + +def pk_decode(pk): + rho, rest = pk[:32], pk[32:] + step = 32 * (23 - D) + return rho, [simple_bit_unpack(rest[i * step:(i + 1) * step], (1 << (23 - D)) - 1) for i in range(K)] + + +def sk_encode(rho, k, tr, s1, s2, t0): + out = rho + k + tr + out += b"".join(bit_pack(s, ETA, ETA) for s in s1) + out += b"".join(bit_pack(s, ETA, ETA) for s in s2) + out += b"".join(bit_pack(t, (1 << (D - 1)) - 1, 1 << (D - 1)) for t in t0) + return out + + +def sk_decode(sk): + rho, k, tr = sk[:32], sk[32:64], sk[64:128] + pos = 128 + s1, s2, t0 = [], [], [] + for _ in range(L): + s1.append(bit_unpack(sk[pos:pos + 128], ETA, ETA)) + pos += 128 + for _ in range(K): + s2.append(bit_unpack(sk[pos:pos + 128], ETA, ETA)) + pos += 128 + for _ in range(K): + t0.append(bit_unpack(sk[pos:pos + 32 * D], (1 << (D - 1)) - 1, 1 << (D - 1))) + pos += 32 * D + return rho, k, tr, s1, s2, t0 + + +def sig_encode(c_tilde, z, h): + return c_tilde + b"".join(bit_pack(zi, GAMMA1 - 1, GAMMA1) for zi in z) + hint_bit_pack(h) + + +def sig_decode(sigma): + c_tilde = sigma[:LAMBDA // 4] + pos = LAMBDA // 4 + z = [] + for _ in range(L): + z.append(bit_unpack(sigma[pos:pos + 32 * 20], GAMMA1 - 1, GAMMA1)) + pos += 32 * 20 + h = hint_bit_unpack(sigma[pos:]) + return c_tilde, z, h + + +def w1_encode(w1): + return b"".join(simple_bit_pack(w, (Q - 1) // (2 * GAMMA2) - 1) for w in w1) + + +# --- the scheme (FIPS 204 §6) ------------------------------------------------------------------------------- + + +def _matvec(a_hat, v_hat): + out = [] + for i in range(K): + acc = [0] * N + for j in range(L): + acc = _add(acc, _mul(a_hat[i][j], v_hat[j])) + out.append(acc) + return out + + +def keygen(seed): + """ML-DSA.KeyGen_internal: (public key, secret key) bytes for a 32-byte seed.""" + if len(seed) != 32: + raise ValueError("the seed is 32 bytes") + h = _shake256(seed + bytes([K, L]), 128) + rho, rho_prime, kk = h[:32], h[32:96], h[96:] + a_hat = expand_a(rho) + s1, s2 = expand_s(rho_prime) + t = [_add(ntt_inv(row), s2i) for row, s2i in zip(_matvec(a_hat, [ntt(s) for s in s1]), s2)] + t1, t0 = [], [] + for poly in t: + hi, lo = zip(*(power2round(c) for c in poly)) + t1.append(list(hi)) + t0.append(list(lo)) + pk = pk_encode(rho, t1) + tr = _shake256(pk, 64) + return pk, sk_encode(rho, kk, tr, s1, s2, t0) + + +def public_key(seed): + return keygen(seed)[0] + + +def _message_representative(message, ctx=b""): + if len(ctx) > 255: + raise ValueError("the context is at most 255 bytes") + return bytes([0, len(ctx)]) + ctx + message + + +def sign(sk, message, ctx=b"", rnd=bytes(32)): + """ML-DSA.Sign with the deterministic variant (rnd = 0): the 3309-byte signature.""" + rho, kk, tr, s1, s2, t0 = sk_decode(sk) + s1_hat = [ntt(s) for s in s1] + s2_hat = [ntt(s) for s in s2] + t0_hat = [ntt(t) for t in t0] + a_hat = expand_a(rho) + mu = _shake256(tr + _message_representative(message, ctx), 64) + rho_pp = _shake256(kk + rnd + mu, 64) + kappa = 0 + while True: + y = expand_mask(rho_pp, kappa) + w = [ntt_inv(row) for row in _matvec(a_hat, [ntt(yi) for yi in y])] + w1 = [[high_bits(c) for c in wi] for wi in w] + c_tilde = _shake256(mu + w1_encode(w1), LAMBDA // 4) + c = sample_in_ball(c_tilde) + c_hat = ntt(c) + cs1 = [ntt_inv(_mul(c_hat, s)) for s in s1_hat] + cs2 = [ntt_inv(_mul(c_hat, s)) for s in s2_hat] + z = [_add(yi, ci) for yi, ci in zip(y, cs1)] + r0 = [[low_bits(c) for c in _sub(wi, ci)] for wi, ci in zip(w, cs2)] + kappa += L + if max(_inf_norm(zi) for zi in z) >= GAMMA1 - BETA or max(max(abs(c) for c in r) for r in r0) >= GAMMA2 - BETA: + continue + ct0 = [ntt_inv(_mul(c_hat, t)) for t in t0_hat] + h = [] + for i in range(K): + base = _add(_sub(w[i], cs2[i]), ct0[i]) + h.append([make_hint((-ct0[i][j]) % Q, base[j]) for j in range(N)]) + if max(_inf_norm(t) for t in ct0) >= GAMMA2 or sum(sum(hi) for hi in h) > OMEGA: + continue + z_signed = [[_mod_pm(c, Q) for c in zi] for zi in z] + return sig_encode(c_tilde, z_signed, h) + + +def verify(pk, message, signature, ctx=b""): + """ML-DSA.Verify: True for a valid signature of `message` under `pk`. Never raises.""" + try: + if len(pk) != PK_SIZE or len(signature) != SIG_SIZE or len(ctx) > 255: + return False + rho, t1 = pk_decode(pk) + c_tilde, z, h = sig_decode(signature) + if h is None: + return False + a_hat = expand_a(rho) + tr = _shake256(pk, 64) + mu = _shake256(tr + _message_representative(message, ctx), 64) + c_hat = ntt(sample_in_ball(c_tilde)) + az = _matvec(a_hat, [ntt(zi) for zi in z]) + ct1 = [_mul(c_hat, ntt([c << D for c in t])) for t in t1] + w_approx = [ntt_inv(_sub(a, b)) for a, b in zip(az, ct1)] + w1 = [[use_hint(h[i][j], w_approx[i][j]) for j in range(N)] for i in range(K)] + if max(_inf_norm(zi) for zi in z) >= GAMMA1 - BETA: + return False + return _shake256(mu + w1_encode(w1), LAMBDA // 4) == c_tilde + except (ValueError, TypeError, IndexError): + return False diff --git a/tools/oracle/model.py b/tools/oracle/model.py new file mode 100644 index 0000000..9a85991 --- /dev/null +++ b/tools/oracle/model.py @@ -0,0 +1,162 @@ +"""The node tree of scienting-doc/1. + +Non-normative; see spec/03-nodes.md. +""" + +BLOCKS = frozenset( + ["paragraph", "equation", "figure", "table", "list", "quote", "code", "algorithm", "theorem", "footnote"] +) + +# Allowed child kinds for each node kind. +CHILDREN = { + "document": frozenset(["front", "section", "back"]), + "front": frozenset(["title", "authors", "abstract", "keywords", "notes"]), + "title": frozenset(["sentence"]), + "authors": frozenset(), + "abstract": BLOCKS | {"section"}, + "keywords": frozenset(), + "notes": frozenset(["footnote", "paragraph"]), + "section": BLOCKS | {"heading", "section"}, + "heading": frozenset(["sentence"]), + "paragraph": frozenset(["sentence"]), + "sentence": frozenset(["equation"]), + "equation": frozenset(["equation-line"]), + "equation-line": frozenset(), + "figure": frozenset(["panel", "caption", "figure-note"]), + "panel": frozenset(), + "caption": frozenset(["sentence"]), + "figure-note": frozenset(["sentence"]), + "table": frozenset(["caption", "table-head", "table-body", "table-note"]), + "table-head": frozenset(["row"]), + "table-body": frozenset(["row"]), + "table-note": frozenset(["sentence"]), + "row": frozenset(["cell"]), + "cell": frozenset(), + "list": frozenset(["item"]), + "item": BLOCKS, + "quote": BLOCKS, + "code": frozenset(), + "algorithm": frozenset(), + "theorem": BLOCKS, + "footnote": frozenset(["sentence"]), + "back": frozenset(["acknowledgments", "references", "appendix", "notes"]), + "acknowledgments": BLOCKS, + "references": frozenset(["reference"]), + "reference": frozenset(), + "appendix": frozenset(["section"]), +} +KINDS = frozenset(CHILDREN) + +# Kinds that must have at least one child. +NONEMPTY = frozenset( + ["title", "heading", "paragraph", "caption", "figure-note", "table-note", "table-head", "table-body", + "row", "list", "item", "quote", "theorem", "footnote", "appendix"] +) +# Kinds that occur at most once among their siblings. +AT_MOST_ONCE = frozenset( + ["front", "back", "title", "authors", "abstract", "keywords", "caption", "table-head", "table-body", + "acknowledgments", "references"] +) + +RUN_KINDS = frozenset(["sentence", "cell", "reference", "authors", "keywords"]) +MATH_KINDS = frozenset(["equation", "equation-line"]) +VERBATIM_KINDS = frozenset(["code", "algorithm"]) +LEAVES = RUN_KINDS | MATH_KINDS | VERBATIM_KINDS +CONTAINERS_WITH_CONTENT = frozenset(["section", "figure", "panel", "table", "theorem", "footnote"]) +CONTAINERS_WITHOUT_CONTENT = KINDS - LEAVES - CONTAINERS_WITH_CONTENT +LABELLED = frozenset( + ["section", "figure", "panel", "table", "theorem", "footnote", "equation", "equation-line", "reference", + "code", "algorithm"] +) + +# The attributes each kind may carry (spec/03 §3.4); kinds absent here carry none. +ATTRS = { + "section": frozenset(["level"]), + "table": frozenset(["columns"]), + "cell": frozenset(["column", "rowspan", "colspan", "role"]), + "row": frozenset(["header_path"]), + "list": frozenset(["ordered"]), + "item": frozenset(["marker"]), + "theorem": frozenset(["variant"]), + "panel": frozenset(["image", "crop", "figure_text"]), +} + +RUNS = frozenset(["text", "math", "cite", "xref", "fnmark", "link", "equation"]) +STYLES = frozenset(["em", "strong", "sup", "sub", "sc", "mono"]) + +LEVELS = ["F0", "F1", "F2", "F3"] + + +def anchor_class(kind): + if kind in LEAVES: + return "leaf" + if kind in CONTAINERS_WITH_CONTENT: + return "container-with-content" + return "container-without-content" + + +class Doc: + """A document: nodes by ID with parent and order, plus document order.""" + + def __init__(self, key, nodes): + self.key = key + self.nodes = {} + self.order = [] + self.children = {} + for n in nodes: + self.nodes[n["id"]] = n + self.order.append(n["id"]) + self.children.setdefault(n["id"], []) + for nid in self.order: + p = self.nodes[nid].get("parent") + if p is not None: + self.children.setdefault(p, []).append(nid) + for p, kids in self.children.items(): + kids.sort(key=lambda c: self.nodes[c]["ord"]) + roots = [nid for nid in self.order if self.nodes[nid].get("parent") is None] + self.root = roots[0] if roots else None + + def kids(self, nid): + return self.children.get(nid, []) + + def preorder(self, nid=None): + nid = self.root if nid is None else nid + out = [] + stack = [nid] + while stack: + x = stack.pop() + out.append(x) + stack.extend(reversed(self.kids(x))) + return out + + def ancestors(self, nid): + out = [] + p = self.nodes[nid].get("parent") + while p is not None: + out.append(p) + p = self.nodes[p].get("parent") + return list(reversed(out)) + + def text_leaves(self, nid): + """The text-bearing nodes a container's projections are made of, in document order.""" + out = [] + stack = [nid] + while stack: + x = stack.pop() + n = self.nodes[x] + k = n["kind"] + if k in RUN_KINDS or k in VERBATIM_KINDS or (k == "equation" and self._parent_kind(x) != "sentence"): + out.append(x) + continue + if k == "equation-line" or k == "equation": + continue + stack.extend(reversed(self.kids(x))) + return out + + def leaves(self, nid): + """Every leaf below or at `nid`, including equations inside sentences and equation lines.""" + return [x for x in self.preorder(nid) if self.nodes[x]["kind"] in LEAVES] + + def _parent_kind(self, nid): + p = self.nodes[nid].get("parent") + return None if p is None else self.nodes[p]["kind"] diff --git a/tools/oracle/notation.py b/tools/oracle/notation.py new file mode 100644 index 0000000..5a675ce --- /dev/null +++ b/tools/oracle/notation.py @@ -0,0 +1,481 @@ +"""Simple notation and its canonical linear form. + +Non-normative; the rules are spec/05-hashes.md, "The strict projection". +A math source or a styled script either folds to one canonical linear form, or is complex. +""" + +import unicodedata + +from .text import collapse_ws, is_ws, remove_ws, trim + +MINUS = "\u2212" +DOT = "\u22c5" +PRIME = "\u2032" + +# Characters that fold to one canonical character inside notation. +CHAR_FOLD = { + "-": MINUS, + "\u2013": MINUS, + "\u2212": MINUS, + "\u00b7": DOT, + "\u2219": DOT, + "\u22c5": DOT, + "'": PRIME, + "\u2032": PRIME, +} + +OPERATORS = set("+=/<>.,()") | {MINUS, DOT, PRIME, "\u00d7", "\u2264", "\u2265", "\u00b1"} + +TEX_GREEK = { + "alpha": "\u03b1", "beta": "\u03b2", "gamma": "\u03b3", "delta": "\u03b4", + "epsilon": "\u03f5", "varepsilon": "\u03b5", "zeta": "\u03b6", "eta": "\u03b7", + "theta": "\u03b8", "vartheta": "\u03d1", "iota": "\u03b9", "kappa": "\u03ba", + "varkappa": "\u03f0", "lambda": "\u03bb", "mu": "\u03bc", "nu": "\u03bd", + "xi": "\u03be", "pi": "\u03c0", "varpi": "\u03d6", "rho": "\u03c1", + "varrho": "\u03f1", "sigma": "\u03c3", "varsigma": "\u03c2", "tau": "\u03c4", + "upsilon": "\u03c5", "phi": "\u03d5", "varphi": "\u03c6", "chi": "\u03c7", + "psi": "\u03c8", "omega": "\u03c9", + "Gamma": "\u0393", "Delta": "\u0394", "Theta": "\u0398", "Lambda": "\u039b", + "Xi": "\u039e", "Pi": "\u03a0", "Sigma": "\u03a3", "Upsilon": "\u03a5", + "Phi": "\u03a6", "Psi": "\u03a8", "Omega": "\u03a9", +} +TEX_SYMBOLS = { + "times": "\u00d7", "cdot": DOT, "pm": "\u00b1", "le": "\u2264", "leq": "\u2264", + "ge": "\u2265", "geq": "\u2265", "lt": "<", "gt": ">", "prime": PRIME, + "AA": "\u00c5", +} +TEX_WRAPPERS = {"mathrm", "text", "textrm", "mathup"} +TEX_DECLARATIONS = {"rm"} +TEX_SPACES = {"quad", "qquad", "enspace", "thinspace", "medspace", "thickspace"} +TEX_SPACE_SYMBOLS = {",", ";", ":", "!", " "} + +TYPST_GREEK = { + "alpha": "\u03b1", "beta": "\u03b2", "gamma": "\u03b3", "delta": "\u03b4", + "epsilon": "\u03b5", "zeta": "\u03b6", "eta": "\u03b7", "theta": "\u03b8", + "iota": "\u03b9", "kappa": "\u03ba", "lambda": "\u03bb", "mu": "\u03bc", + "nu": "\u03bd", "xi": "\u03be", "omicron": "\u03bf", "pi": "\u03c0", + "rho": "\u03c1", "sigma": "\u03c3", "tau": "\u03c4", "upsilon": "\u03c5", + "phi": "\u03c6", "chi": "\u03c7", "psi": "\u03c8", "omega": "\u03c9", + "Alpha": "\u0391", "Beta": "\u0392", "Gamma": "\u0393", "Delta": "\u0394", + "Epsilon": "\u0395", "Zeta": "\u0396", "Eta": "\u0397", "Theta": "\u0398", + "Iota": "\u0399", "Kappa": "\u039a", "Lambda": "\u039b", "Mu": "\u039c", + "Nu": "\u039d", "Xi": "\u039e", "Omicron": "\u039f", "Pi": "\u03a0", + "Rho": "\u03a1", "Sigma": "\u03a3", "Tau": "\u03a4", "Upsilon": "\u03a5", + "Phi": "\u03a6", "Chi": "\u03a7", "Psi": "\u03a8", "Omega": "\u03a9", + "epsilon.alt": "\u03f5", "theta.alt": "\u03d1", "phi.alt": "\u03d5", + "pi.alt": "\u03d6", "rho.alt": "\u03f1", "sigma.alt": "\u03c2", + "kappa.alt": "\u03f0", "beta.alt": "\u03d0", +} +TYPST_SYMBOLS = { + "plus": "+", "minus": MINUS, "times": "\u00d7", "dot": DOT, "dot.op": DOT, + "dot.c": DOT, "plus.minus": "\u00b1", "lt": "<", "gt": ">", "lt.eq": "\u2264", + "gt.eq": "\u2265", "eq": "=", "prime": PRIME, "slash": "/", +} +TYPST_WRAPPERS = {"upright"} +TYPST_SPACES = {"thin", "med", "thick", "quad", "wide", "space"} + + +class NotSimple(Exception): + pass + + +# The Latin and Greek letter blocks of spec/05 \u00a75.4: Basic Latin through Latin Extended-B, Greek and Coptic without +# the Coptic letters, Latin Extended Additional, and Greek Extended. +LETTER_RANGES = ((0x0041, 0x024F), (0x0370, 0x03E1), (0x03F0, 0x03FF), (0x1E00, 0x1EFF), (0x1F00, 0x1FFF)) + + +def is_letter(ch): + """A letter of General Category L in the Latin or Greek blocks, or the micro sign.""" + if ch == "\u00b5": + return True + if not unicodedata.category(ch).startswith("L"): + return False + cp = ord(ch) + return any(lo <= cp <= hi for lo, hi in LETTER_RANGES) + + +def fold_char(ch): + return CHAR_FOLD.get(ch, ch) + + +def is_simple_char(ch): + ch = fold_char(ch) + return is_letter(ch) or unicodedata.category(ch) == "Nd" or ch in OPERATORS + + +def script_type(ch): + d = unicodedata.decomposition(ch) + if d.startswith("<super>"): + return "^", "".join(chr(int(h, 16)) for h in d.split()[1:]) + if d.startswith("<sub>"): + return "_", "".join(chr(int(h, 16)) for h in d.split()[1:]) + return None, None + + +class Atom: + __slots__ = ("base", "primes", "sub", "sup") + + def __init__(self, base=""): + self.base = base + self.primes = 0 + self.sub = None + self.sup = None + + +def _canon(atoms): + out = [] + for a in atoms: + if a.sup is not None and a.sup and all( + x.base == PRIME and x.sub is None and x.sup is None and x.primes == 0 for x in a.sup + ): + a.primes += len(a.sup) + a.sup = None + s = a.base + PRIME * a.primes + if a.sub is not None: + s += "_{" + _canon(a.sub) + "}" + if a.sup is not None: + s += "^{" + _canon(a.sup) + "}" + out.append(s) + return "".join(out) + + +def _attach(atoms, op, arg): + if not atoms: + atoms.append(Atom("")) + a = atoms[-1] + if op == "_": + if a.sub is not None: + raise NotSimple("double subscript") + a.sub = arg + else: + if a.sup is not None: + raise NotSimple("double superscript") + a.sup = arg + + +def _char_atom(ch): + if not is_simple_char(ch): + raise NotSimple("character %r" % ch) + return Atom(fold_char(ch)) + + +# --- TeX --------------------------------------------------------------------- + + +def _tex_tokens(src): + toks = [] + i, n = 0, len(src) + while i < n: + ch = src[i] + if ch == "\\": + j = i + 1 + if j < n and src[j].isascii() and src[j].isalpha(): + while j < n and src[j].isascii() and src[j].isalpha(): + j += 1 + toks.append(("cw", src[i + 1:j])) + while j < n and is_ws(src[j]): + j += 1 + i = j + continue + if j < n: + toks.append(("cs", src[j])) + i = j + 1 + continue + raise NotSimple("trailing backslash") + if is_ws(ch) or ch == "~": + i += 1 + continue + toks.append(("ch", ch)) + i += 1 + return toks + + +class _TexParser: + def __init__(self, toks): + self.t = toks + self.i = 0 + + def peek(self): + return self.t[self.i] if self.i < len(self.t) else None + + def take(self): + tok = self.peek() + self.i += 1 + return tok + + def seq(self, closing): + atoms = [] + while True: + tok = self.peek() + if tok is None: + if closing: + raise NotSimple("unclosed group") + return atoms + if tok == ("ch", "}"): + if not closing: + raise NotSimple("unbalanced brace") + self.take() + return atoms + self.take() + kind, val = tok + if kind == "ch" and val in "_^": + _attach(atoms, val, self.arg()) + elif kind == "ch" and val == "'": + if not atoms: + atoms.append(Atom("")) + atoms[-1].primes += 1 + elif kind == "ch" and val == "{": + inner = self.seq(True) + nxt = self.peek() + if nxt in (("ch", "_"), ("ch", "^")) and len(inner) > 1: + raise NotSimple("script on a multi-atom group") + atoms.extend(inner) # an empty group leaves a following script to the previous atom or an empty base + else: + atoms.extend(self.command_or_char(kind, val)) + + def command_or_char(self, kind, val): + if kind == "ch": + return [_char_atom(val)] + if kind == "cs": + if val in TEX_SPACE_SYMBOLS: + return [] + raise NotSimple("control symbol \\" + val) + if val in TEX_GREEK: + return [Atom(TEX_GREEK[val])] + if val in TEX_SYMBOLS: + return [Atom(TEX_SYMBOLS[val])] + if val in TEX_SPACES or val in TEX_DECLARATIONS: + return [] + if val in TEX_WRAPPERS: + return self.arg() + if val in ("left", "right"): + tok = self.take() + if tok == ("ch", "(" if val == "left" else ")"): + return [Atom(tok[1])] + raise NotSimple("\\left or \\right with another delimiter") + raise NotSimple("command \\" + val) + + def arg(self): + tok = self.take() + if tok is None: + raise NotSimple("missing argument") + kind, val = tok + if tok == ("ch", "{"): + return self.seq(True) + if kind == "ch" and val in "}_^'": + raise NotSimple("bad argument") + return self.command_or_char(kind, val) + + +def tex_atoms(src): + return _TexParser(_tex_tokens(src)).seq(False) + + +# --- Typst ------------------------------------------------------------------- + + +def _typst_tokens(src): + toks = [] + i, n = 0, len(src) + while i < n: + ch = src[i] + if is_ws(ch): + i += 1 + continue + if ch == '"': + j = i + 1 + buf = [] + while j < n and src[j] != '"': + if src[j] == "\\": + raise NotSimple("escape in string") + buf.append(src[j]) + j += 1 + if j >= n: + raise NotSimple("unclosed string") + toks.append(("str", "".join(buf))) + i = j + 1 + continue + if unicodedata.category(ch).startswith("L"): + j = i + while j < n and ( + unicodedata.category(src[j]).startswith("L") + or (src[j] == "." and j + 1 < n and src[j + 1].isascii() and src[j + 1].isalpha() and j > i) + ): + j += 1 + toks.append(("id", src[i:j])) + i = j + continue + if unicodedata.category(ch) == "Nd": + j = i + while j < n and unicodedata.category(src[j]) == "Nd": + j += 1 + if j + 1 < n and src[j] == "." and unicodedata.category(src[j + 1]) == "Nd": + j += 1 + while j < n and unicodedata.category(src[j]) == "Nd": + j += 1 + toks.append(("num", src[i:j])) + i = j + continue + two = src[i:i + 2] + if two in ("<=", ">="): + toks.append(("ch", "\u2264" if two == "<=" else "\u2265")) + i += 2 + continue + if two in ("->", "=>", "!=", "<-", "==", ":="): + raise NotSimple("operator " + two) + toks.append(("ch", ch)) + i += 1 + return toks + + +class _TypstParser: + def __init__(self, toks): + self.t = toks + self.i = 0 + + def peek(self): + return self.t[self.i] if self.i < len(self.t) else None + + def take(self): + tok = self.peek() + self.i += 1 + return tok + + def seq(self, closing): + atoms = [] + while True: + tok = self.peek() + if tok is None: + if closing: + raise NotSimple("unclosed parenthesis") + return atoms + if closing and tok == ("ch", ")"): + self.take() + return atoms + self.take() + kind, val = tok + if kind == "ch" and val in "_^": + _attach(atoms, val, self.arg()) + elif kind == "ch" and val == "'": + if not atoms: + atoms.append(Atom("")) + atoms[-1].primes += 1 + elif kind == "ch" and val == "(": + atoms.append(Atom("(")) + atoms.extend(self.seq(True)) + atoms.append(Atom(")")) + else: + atoms.extend(self.single(kind, val)) + + def single(self, kind, val): + if kind == "num": + return [Atom(c) for c in val] + if kind == "str": + return [_char_atom(c) for c in remove_ws(val)] + if kind == "id": + if len(val) == 1: + return [_char_atom(val)] + if val in TYPST_GREEK: + return [Atom(TYPST_GREEK[val])] + if val in TYPST_SYMBOLS: + return [Atom(TYPST_SYMBOLS[val])] + if val in TYPST_SPACES: + return [] + if val in TYPST_WRAPPERS and self.peek() == ("ch", "("): + self.take() + return self.seq(True) + raise NotSimple("identifier " + val) + if val in "/*#&[]{}\\$!:;|~@": + raise NotSimple("character %r" % val) + return [_char_atom(val)] + + def arg(self): + tok = self.take() + if tok is None: + raise NotSimple("missing argument") + kind, val = tok + if tok == ("ch", "("): + return self.seq(True) + if kind == "ch" and val in ")_^'": + raise NotSimple("bad argument") + return self.single(kind, val) + + +def typst_atoms(src): + return _TypstParser(_typst_tokens(src)).seq(False) + + +# --- public ------------------------------------------------------------------ + + +def fold_math(notation, source): + """Return the canonical linear form of a math source, or None when it is complex.""" + src = unicodedata.normalize("NFC", source) + try: + atoms = tex_atoms(src) if notation == "tex" else typst_atoms(src) + return _canon(atoms) + except NotSimple: + return None + + +def complex_key(notation, source): + return notation + ":" + remove_ws(unicodedata.normalize("NFC", source)) + + +def _fold_script_chars(chars): + """Fold a run of Unicode script characters of one type, or None if any base is not simple.""" + op = None + bases = [] + for ch in chars: + t, b = script_type(ch) + if t is None or (op is not None and t != op): + return None + op = t + bases.append(b) + base = "".join(bases) + if not all(is_simple_char(c) for c in base): + return None + return op + "{" + "".join(fold_char(c) for c in base) + "}" + + +def _fold_chars(s, in_notation): + """Fold the characters of text: script characters always, operators only inside notation.""" + out = [] + i, n = 0, len(s) + while i < n: + ch = s[i] + t, b = script_type(ch) + if t is not None: + j = i + while j < n and script_type(s[j])[0] == t: + j += 1 + folded = _fold_script_chars(s[i:j]) + out.append(folded if folded is not None else s[i:j]) + i = j + continue + if in_notation: + out.append(fold_char(ch)) + elif ch in ("-", "\u2013") and i + 1 < n and unicodedata.category(s[i + 1]) == "Nd": + out.append(MINUS) + else: + out.append(ch) + i += 1 + return "".join(out) + + +def fold_plain_text(text): + return _fold_chars(unicodedata.normalize("NFC", text), in_notation=False) + + +def fold_styled_script(op, text): + """The canonical form of text styled as a subscript (`_`) or superscript (`^`).""" + t = unicodedata.normalize("NFC", text) + s = remove_ws(t) + simple = all(is_simple_char(c) or script_type(c)[0] is not None for c in s) + if simple: + inner = _fold_chars(s, in_notation=True) + if op == "^" and inner and all(c == PRIME for c in inner): + return inner + else: + inner = trim(collapse_ws(t)) + return op + "{" + inner + "}" diff --git a/tools/oracle/package.py b/tools/oracle/package.py new file mode 100644 index 0000000..9efe310 --- /dev/null +++ b/tools/oracle/package.py @@ -0,0 +1,628 @@ +"""Packages: writing, reading and validating a scienting-doc/1 package folder. + +Non-normative; see spec/12-package.md and spec/22-conformance.md. +""" + +import base64 +import binascii +import hashlib +import json +import os +import posixpath +import re +import stat +import tempfile +import unicodedata +import zipfile + +from . import crypto, hashing, jcs, keys as K, receipts as R, vrf +from .anchors import ADDRESS_RE +from .model import LEAVES, MATH_KINDS, RUN_KINDS, VERBATIM_KINDS, Doc +from .schema import validate as schema_validate +from .text import KEY_RE, letter_first, record_id, sha256_hex +from .tree import Refusal, validate_references, validate_structure + +# The reference tools' own limit on a package's total size (spec/12 §12.2 leaves the limit to the consumer). +SIZE_LIMIT = 1 << 30 + +JSONL = { + "nodes.jsonl": "node.schema.json", + "pages.jsonl": "page.schema.json", + "locations.jsonl": "location.schema.json", + "references.jsonl": "reference.schema.json", + "corrections.jsonl": "correction.schema.json", + "receipts.jsonl": None, + "ids.jsonl": "id-entry.schema.json", + "suspects.jsonl": "suspect.schema.json", +} +JSON = { + "document.json": "document.schema.json", + "witnesses.json": "witnesses.schema.json", + "provenance.json": "provenance.schema.json", + "roster.json": "roster.schema.json", +} +REQUIRED = ["document.json", "nodes.jsonl", "witnesses.json", "provenance.json"] + + +def line(rec): + return jcs.dumps(rec) + "\n" + + +def jsonl(recs): + return "".join(line(r) for r in recs).encode("utf-8") + + +def witness_id(sha): + return letter_first(bytes.fromhex(sha), 7) + + +SHA256_RE = re.compile(r"[0-9a-f]{64}") + + +def safe_path(p): + if not isinstance(p, str) or not p or p.startswith("/") or "\\" in p or "\x00" in p: + return False + parts = p.split("/") + return all(x not in ("", ".", "..") for x in parts) and posixpath.normpath(p) == p + + +def write(root, files, absent=()): + """Write `files` ({path: bytes}) and a MANIFEST.json listing them and the `absent` entries. + + Returns the package hash. + """ + for path in list(files) + [a["path"] for a in absent]: + if not safe_path(path) or path == "MANIFEST.json": + raise Refusal("package.path.unsafe", "unsafe path %r" % path) + os.makedirs(root, exist_ok=True) + entries = [dict(a) for a in absent] + for path in sorted(files, key=lambda p: p.encode("utf-8")): + data = files[path] + if data is None: + continue + full = os.path.join(root, path) + os.makedirs(os.path.dirname(full), exist_ok=True) + with open(full, "wb") as f: + f.write(data) + entries.append({"path": path, "sha256": sha256_hex(data), "size": len(data)}) + entries.sort(key=lambda e: e["path"].encode("utf-8")) + doc = json.loads(files["document.json"]) + manifest = {"format": "scienting-package/1", "doc": "scienting-doc/1", "key": doc["key"], "files": entries} + mb = (jcs.dumps(manifest) + "\n").encode("utf-8") + with open(os.path.join(root, "MANIFEST.json"), "wb") as f: + f.write(mb) + return sha256_hex(mb) + + +def _refuse_constant(name): + raise ValueError("JSON has no canonical form for " + name) + + +def _parse_int(text): + """Read a JSON integer as an ECMAScript engine would: exactly within 2^53, as a double beyond (spec/01 §1.1).""" + v = int(text) + return v if abs(v) <= 2**53 else float(v) + + +def _canonical_bytes(data, where): + """Parse one canonical JSON value given as bytes; refuse anything else (spec/01 §1.1, §1.9). + + Numbers are read as IEEE 754 doubles, as the canonical form writes them, and the comparison is on bytes, so a + carriage return, a byte order mark, a lone surrogate, NaN or invalid UTF-8 is refused, not silently translated. + """ + try: + rec = json.loads(data.decode("utf-8"), parse_constant=_refuse_constant, parse_int=_parse_int) + canon = jcs.dumps(rec).encode("utf-8") + except (UnicodeDecodeError, ValueError, TypeError, OverflowError, RecursionError) as e: + raise Refusal("package.file.canonical", "%s: not canonical JSON (%s)" % (where, type(e).__name__)) + if canon != data: + raise Refusal("package.file.canonical", "%s: not canonical JSON" % where) + return rec + + +def read_jsonl(path): + with open(path, "rb") as f: + data = f.read() + if data and not data.endswith(b"\n"): + raise Refusal("package.file.newline", "%s: every line ends with a newline" % path) + return [_canonical_bytes(ln, "%s:%d" % (path, i)) for i, ln in enumerate(data.split(b"\n")[:-1], 1)] + + +def read_json(path): + with open(path, "rb") as f: + data = f.read() + if not data.endswith(b"\n"): + raise Refusal("package.file.canonical", "%s: the file does not end with one newline" % path) + return _canonical_bytes(data[:-1], path) + + +class Report: + def __init__(self): + self.errors = [] + + def add(self, rule, where, message): + self.errors.append({"rule": rule, "where": where, "message": message}) + + def __bool__(self): + return not self.errors + + +def _all_files(root): + """Every file under `root` by its exact name, refusing any symbolic link on the way (spec/12 §12.2).""" + out = [] + for d, dirs, fs in os.walk(root): + for name in dirs + fs: + if os.path.islink(os.path.join(d, name)): + rel = os.path.relpath(os.path.join(d, name), root).replace(os.sep, "/") + raise Refusal("package.path.unsafe", "%s: symbolic links are refused" % rel) + for f in fs: + out.append(os.path.relpath(os.path.join(d, f), root).replace(os.sep, "/")) + return sorted(out) + + +def _hash_file(full, budget): + """SHA-256 and size of a file read in chunks, refusing a read past `budget` bytes.""" + h, n = hashlib.sha256(), 0 + with open(full, "rb") as fh: + while True: + chunk = fh.read(1 << 20) + if not chunk: + break + n += len(chunk) + if n > budget: + raise Refusal("package.size", "the package's files exceed the limit of %d bytes" % SIZE_LIMIT) + h.update(chunk) + return h.hexdigest(), n + + +def validate(root, store, key=None, limit=SIZE_LIMIT): + """Validate the package at `root`. `store` is a schema store; `key` a hashing key for keyed packages; + `limit` the most bytes the validator reads before refusing.""" + rep = Report() + try: + _validate(root, store, key, rep, limit) + except Refusal as e: + rep.add(e.rule, e.node or "", e.message) + return rep + + +def _validate(root, store, key, rep, limit=SIZE_LIMIT): + mpath = os.path.join(root, "MANIFEST.json") + if not os.path.lexists(mpath): + raise Refusal("package.manifest.missing", "MANIFEST.json is missing") + actual = set(_all_files(root)) + manifest = read_json(mpath) + for e in schema_validate(store, "manifest.schema.json", manifest): + rep.add("package.manifest.schema", "MANIFEST.json", e) + if not rep: + return + listed = {} + paths = [f["path"] for f in manifest["files"]] + if paths != sorted(paths, key=lambda p: p.encode("utf-8")) or len(set(paths)) != len(paths): + rep.add("package.manifest.order", "MANIFEST.json", "files must be sorted by path and unique") + folded = {} + budget = limit + for f in manifest["files"]: + p = f["path"] + listed[p] = f + if not safe_path(p) or p == "MANIFEST.json": + rep.add("package.path.unsafe", p, "unsafe path") + continue + fold = unicodedata.normalize("NFC", p).casefold() + if fold in folded: + rep.add("package.manifest.order", p, "collides with %s under case folding" % folded[fold]) + folded[fold] = p + if f.get("present", True) is False: + if not p.startswith("assets/"): + rep.add("package.manifest.absent", p, "only assets may be listed without their bytes") + if p in actual: + rep.add("package.manifest.absent", p, "a file listed as absent is present") + continue + if p not in actual: + rep.add("package.manifest.missing-file", p, "listed file is missing") + continue + sha, size = _hash_file(os.path.join(root, p), budget) + budget -= size + if sha != f["sha256"] or size != f["size"]: + rep.add("package.manifest.hash", p, "SHA-256 or size does not match the manifest") + for p in sorted(actual): + if p != "MANIFEST.json" and p not in listed: + rep.add("package.manifest.unlisted", p, "file is not listed in the manifest") + for p in REQUIRED: + if p not in listed: + rep.add("package.file.required", p, "required file is missing") + if not rep: + return + + data = {} + for p, sch in JSON.items(): + if p in listed: + data[p] = read_json(os.path.join(root, p)) + for e in schema_validate(store, sch, data[p]): + rep.add("package.schema", p, e) + for p, sch in JSONL.items(): + if p in listed: + data[p] = read_jsonl(os.path.join(root, p)) + for i, rec in enumerate(data[p], 1): + s = sch + if p == "receipts.jsonl": + s = "receipt.schema.json" if rec.get("format") == "scienting-receipt/1" else "revocation.schema.json" + for e in schema_validate(store, s, rec): + rep.add("package.schema", "%s:%d" % (p, i), e) + if p != "nodes.jsonl" and not data[p]: + rep.add("package.file.empty", p, "an optional JSONL file with no records is omitted") + else: + data[p] = [] + if not rep: + return + + document = data["document.json"] + if document["key"] != manifest["key"]: + rep.add("package.manifest.key", "MANIFEST.json", "key differs from document.json") + # Keys (spec/02 §2.4): the document key is the work key and a version suffix, and the work key's hash part is + # the hash of the work's identifier when it has one. + try: + wkey, sfx = K.split_key(document["key"]) + except ValueError: + wkey, sfx = None, None + if wkey != document["work"]["key"] or sfx != K.version_suffix(document["version"]): + rep.add("doc.key.work", "document.json", "the document key is not the work key with the version's suffix") + elif not K.suffix_agrees(wkey, document["work"].get("same_as"), document.get("meta") or {}): + rep.add("doc.key.suffix", "document.json", "the work key's hash part is not the hash of the work's identifier") + nodes = data["nodes.jsonl"] + doc = Doc(document["key"], nodes) + try: + validate_structure(doc) + except Refusal as e: + rep.add(e.rule, "nodes.jsonl " + (e.node or ""), e.message) + return + + # Policy and hashing. + withheld = [n["id"] for n in nodes if n.get("withheld")] + scheme = document["hashing"]["scheme"] + if document["hashing"].get("algorithm") != "sha-256": + rep.add("doc.hash.algorithm", "document.json", "the hash algorithm is not one this validator implements") + if document["policy"] == "full" and withheld: + rep.add("doc.policy.withheld", "nodes.jsonl", "a full package withholds no text") + if document["policy"] == "checks-only": + bearing = [n["id"] for n in nodes if n["kind"] in LEAVES] + if set(bearing) != set(withheld): + rep.add("doc.policy.withheld", "nodes.jsonl", "a checks-only package withholds every leaf's content") + if scheme == "plain": + rep.add("doc.policy.keyed", "document.json", "a checks-only package carries keyed hashes") + if scheme == "hmac-team" and key is not None and document["hashing"]["key_id"] != crypto.key_id(key): + rep.add("doc.hash.key", "document.json", "key_id does not match the key supplied") + + # References between nodes, and the counts. + kinds = {n["id"]: n["kind"] for n in nodes} + try: + validate_references(doc) + except Refusal as e: + rep.add(e.rule, e.node or "", e.message) + leaves_n = sum(1 for n in nodes if n["kind"] in LEAVES) + if document.get("counts") != {"nodes": len(nodes), "leaves": leaves_n}: + rep.add("doc.counts", "document.json", "counts do not recompute") + + # Hashes. + hasher = hashing.PLAIN if scheme == "plain" else (hashing.Hasher(key) if key else None) + if hasher is not None and not withheld: + vals = hashing.compute(doc, hasher) + for n in nodes: + for k, v in vals[n["id"]].items(): + if n[k] != v: + rep.add("doc.hash." + k.replace("_", "-"), n["id"], "%s does not recompute" % k) + if vals[doc.root]["node_hash"] != document["root"]: + rep.add("doc.hash.root", "document.json", "root does not equal the root node's node_hash") + if hashing.meta_hash(document, hasher) != document["meta_hash"]: + rep.add("doc.hash.meta", "document.json", "meta_hash does not recompute") + else: + vals = {n["id"]: {k: n[k] for k in ("text_hash", "match_hash", "align_key", "own_hash", "node_hash")} + for n in nodes} + if n_root_hash(nodes, doc) != document["root"]: + rep.add("doc.hash.root", "document.json", "root does not equal the root node's node_hash") + + # IDs. + live = set(kinds) + ids = data["ids.jsonl"] + known = set(live) + for i, e in enumerate(ids, 1): + if e["id"] in live: + rep.add("doc.id.retired-live", "ids.jsonl:%d" % i, "%s is both live and in the ID table" % e["id"]) + known.add(e["id"]) + for i, e in enumerate(ids, 1): + s = e.get("successor") + if s is not None and s not in known: + rep.add("doc.id.successor", "ids.jsonl:%d" % i, "successor %s is unknown" % s) + if e["kind"] == "alias" and s not in live: + rep.add("doc.id.alias", "ids.jsonl:%d" % i, "an alias names a live node") + order = sorted(ids, key=lambda e: (0 if e["kind"] == "alias" else 1, e.get("rev", 0), e["id"])) + if order != ids: + rep.add("doc.order.ids", "ids.jsonl", "aliases first by ID, then retirements by revision and ID") + + # Corrections. + cors = data["corrections.jsonl"] + for i, c in enumerate(cors, 1): + if c.get("index") != i: + rep.add("doc.correction.index", "corrections.jsonl:%d" % i, "indexes count from 1 without gaps") + if c["id"] != record_id(sha256_hex(jcs.dumpb({k: v for k, v in c.items() if k != "id"}))): + rep.add("doc.correction.id", "corrections.jsonl:%d" % i, "id does not derive from the record") + if document["policy"] == "checks-only" and (cors or data["suspects.jsonl"]): + rep.add("doc.policy.withheld", "corrections.jsonl", "a checks-only package carries no corrections or suspects") + if document["policy"] == "full" and document["rev"] != len(cors): + rep.add("doc.correction.rev", "document.json", "rev must equal the number of corrections") + if document.get("history") != crypto.history_root(history_items(cors)): + rep.add("doc.history", "document.json", "history is not the root over the corrections") + retired_by = {e["id"]: e for e in ids if e["kind"] == "retired"} + for c in cors: + for r in c.get("retired", []): + if r not in retired_by: + rep.add("doc.id.retired-missing", c["id"], "%s was retired but is not in ids.jsonl" % r) + if not withheld and hasher is not None: + last = {} + for c in cors: + if c.get("target") in live and kinds[c["target"]] in LEAVES: + last[c["target"]] = c + for x in c.get("touched", []): + if x != c.get("target"): + last.pop(x, None) + for nid, c in last.items(): + if c.get("after") and c["after"] != vals[nid]["node_hash"] and not doc.kids(nid): + rep.add("doc.correction.after", c["id"], "the last correction of %s does not end at its hash" % nid) + + # Geometry. + wits = {w["id"]: w for w in data["witnesses.json"]["witnesses"]} + for w in wits.values(): + if w["id"] != witness_id(w["sha256"]): + rep.add("doc.witness.id", w["id"], "a witness ID derives from its SHA-256") + fps = set() + for i, p in enumerate(data["pages.jsonl"], 1): + if p["witness"] not in wits: + rep.add("doc.page.witness", "pages.jsonl:%d" % i, "unknown witness") + fps.add(p["page_fp"]) + porder = sorted(data["pages.jsonl"], key=lambda p: (p["witness"], p["page"])) + if porder != data["pages.jsonl"]: + rep.add("doc.order.pages", "pages.jsonl", "pages sort by witness and page") + pos = {nid: i for i, nid in enumerate(doc.order)} + for i, loc in enumerate(data["locations.jsonl"], 1): + if loc["node"] not in live: + rep.add("doc.location.node", "locations.jsonl:%d" % i, "unknown node") + if loc["page_fp"] not in fps: + rep.add("doc.location.page", "locations.jsonl:%d" % i, "page_fp is not a page of any witness") + lorder = sorted(data["locations.jsonl"], key=lambda l: (pos.get(l["node"], -1), l["page"], l["page_fp"])) + if lorder != data["locations.jsonl"]: + rep.add("doc.order.locations", "locations.jsonl", "locations sort by node order, then page") + for i, ref in enumerate(data["references.jsonl"], 1): + if kinds.get(ref["node"]) != "reference": + rep.add("doc.reference.node", "references.jsonl:%d" % i, "names no reference node") + rorder = sorted(data["references.jsonl"], key=lambda r: pos.get(r["node"], -1)) + if rorder != data["references.jsonl"]: + rep.add("doc.order.references", "references.jsonl", "references follow document order") + + sorder = sorted(data["suspects.jsonl"], key=lambda x: x["id"]) + if sorder != data["suspects.jsonl"]: + rep.add("doc.order.suspects", "suspects.jsonl", "suspects sort by ID") + + # Receipts and fidelity. + roster = {k["id"]: k for k in data.get("roster.json", {}).get("keys", [])} + for k in roster.values(): + if k.get("did") and k["scheme"] in crypto.MULTICODEC: + pub = R._b64(k.get("public", "")) + if pub is None or crypto.did_key(k["scheme"], pub) != k["did"]: + rep.add("doc.roster.did", k["id"], "the did:key is not the one the public key determines") + recs = data["receipts.jsonl"] + rorder = sorted(recs, key=lambda r: (r["at"], r["id"])) + if rorder != recs: + rep.add("doc.order.receipts", "receipts.jsonl", "receipts and revocations sort by time, then ID") + by_id = {r["id"]: r for r in recs} + for r in recs: + if r["id"] != record_id(R.record_hash(r)): + rep.add("doc.receipt.id", r["id"], "id does not derive from the record") + if r["format"] == "scienting-receipt/1": + if r["doc"] != document["key"]: + rep.add("doc.receipt.doc", r["id"], "receipt names another document") + if r["root"] != crypto.merkle_root(crypto.receipt_items(r)): + rep.add("doc.receipt.root", r["id"], "Merkle root does not recompute") + ids_listed = [x[0] for x in r["nodes"]] + if ids_listed != sorted(ids_listed) or len(set(ids_listed)) != len(ids_listed): + rep.add("doc.receipt.nodes", r["id"], "nodes sort by ID without repeats") + if roster: + signer = roster.get(r["by"]) + if not R.verify_signature(r, roster): + rep.add("doc.receipt.signature", r["id"], "signature does not verify") + elif r["signature"]["key"] != r["by"] or not signer or not R.key_valid_at(signer, r["at"]): + rep.add("doc.receipt.signature", r["id"], "the signing key is not the signer's key, valid when signed") + qa = r.get("qa") + if qa: + orig = by_id.get(qa["of"]) + if not orig or orig["format"] != "scienting-receipt/1": + rep.add("doc.qa.of", r["id"], "the spot-checked receipt is not a receipt in this package") + continue + if r["scope"] != "qa:" + qa["of"]: + rep.add("doc.qa.of", r["id"], "the scope names another receipt than qa.of") + if orig["at"] > r["at"]: + rep.add("doc.qa.of", r["id"], "a spot-check is signed after the receipt it checks") + orig_hashes = dict(orig["nodes"]) + if [n for n, _ in r["nodes"]] != qa["sample"] or any(orig_hashes.get(n) != h for n, h in r["nodes"]): + rep.add("doc.qa.sample", r["id"], "the receipt's nodes are not the sampled nodes at the original's hashes") + if not {e["node"] for e in qa["errors"]} <= set(qa["sample"]): + rep.add("doc.qa.sample", r["id"], "an error names a node outside the sample") + try: + seed = base64.b64decode(qa["seed"], validate=True) + except (binascii.Error, ValueError): + rep.add("doc.qa.seed", r["id"], "the seed is not Base64") + continue + if vrf.proof_to_hash(seed) is None: + rep.add("doc.qa.seed", r["id"], "the seed is not a VRF proof") + continue + ck = roster.get(qa["key"]) + if roster: + if not ck or ck["scheme"] != "ed25519" or "spot-check" not in ck["purposes"]: + rep.add("doc.qa.key", r["id"], "the seed key is not a registered Ed25519 spot-check key") + elif not ck["registered_at"] <= orig["at"]: + rep.add("doc.qa.key", r["id"], "the spot-check key was registered after the receipt") + elif vrf.verify(R._b64(ck["public"]) or b"", R.seed_payload(orig), seed) is None: + rep.add("doc.qa.seed", r["id"], "the seed is not the checker's VRF proof for the receipt") + if qa["sample"] != R.sample(orig, seed, qa["rate"], qa["minimum"]): + rep.add("doc.qa.sample", r["id"], "the sample does not follow from the seed") + if not withheld and (roster or not recs): + # Without a roster no receipt can be judged valid, so a package that carries receipts but no roster is + # checked against its store instead; one with neither reports the leaves' own levels. + if R.distribution(R.effective_levels(nodes, vals, recs, roster)) != document["fidelity"]: + rep.add("doc.fidelity.report", "document.json", "the fidelity distribution does not recompute") + + +def read_state(root): + """The current state of the package at `root`, for the gate (spec/11 §11.4): nodes without their values, + the ID table and the corrections applied so far. Validate the package first.""" + from .corrections import State + present = {f["path"] for f in read_json(os.path.join(root, "MANIFEST.json"))["files"]} + + def jl(name): + return read_jsonl(os.path.join(root, name)) if name in present else [] + + values = ("text_hash", "match_hash", "align_key", "own_hash", "node_hash") + nodes = [{k: v for k, v in n.items() if k not in values} for n in jl("nodes.jsonl")] + return State(read_json(os.path.join(root, "document.json"))["key"], nodes, jl("ids.jsonl"), jl("corrections.jsonl")) + + +def n_root_hash(nodes, doc): + return {n["id"]: n for n in nodes}[doc.root]["node_hash"] + + +def history_items(corrections): + """The items of a document's history tree (spec/11 §11.5): one per correction, in order.""" + return [["correction", c["index"], c["id"]] for c in corrections] + + +# --- zipped packages (spec/12 §12.2 and §12.8) ----------------------------------------- + +ZIP_EXTENSION = ".sct.zip" +# The reference tools' own limit on an archive's expanded size (spec/12 §12.2 leaves the limit to the consumer). +ZIP_LIMIT = 1 << 30 +_ZIP_DATE = (1980, 1, 1, 0, 0, 0) +_FLAG_ENCRYPTED = 0x1 +_FLAG_UTF8 = 0x800 + + +def is_zip(path): + return os.path.isfile(path) and path.lower().endswith(".zip") + + +def write_zip(root, path): + """Zip the package folder at `root` the way spec/12 §12.2 says a producer writes a byte-identical archive. + + Entries sit under one top-level folder named by the key, sorted by path, stored, dated 1980-01-01 00:00, + with no extra fields and no directory entries. Returns the SHA-256 of the archive. + """ + key = read_json(os.path.join(root, "document.json"))["key"] + files = _all_files(root) + for p in files: + if p != "MANIFEST.json" and not safe_path(p): + raise Refusal("package.path.unsafe", "unsafe path %r" % p) + with zipfile.ZipFile(path, "w") as zf: + for p in sorted(files, key=lambda x: x.encode("utf-8")): + zi = zipfile.ZipInfo(key + "/" + p, date_time=_ZIP_DATE) + zi.compress_type = zipfile.ZIP_STORED + zi.create_system = 3 + zi.external_attr = 0o644 << 16 + with open(os.path.join(root, p), "rb") as f: + zf.writestr(zi, f.read()) + with open(path, "rb") as f: + return sha256_hex(f.read()) + + +def _zip_entries(zf, limit): + """Check every entry of an open archive as spec/12 §12.2 requires; return the top-level folder.""" + infos = zf.infolist() + if not infos: + raise Refusal("package.zip.entry", "the archive has no entries") + folder, seen, total = None, set(), 0 + for zi in infos: + name = zi.filename + if not (zi.flag_bits & _FLAG_UTF8) and any(ord(ch) > 0x7F for ch in name): + raise Refusal("package.zip.entry", "%r: entry name is not marked as UTF-8" % name) + if zi.flag_bits & _FLAG_ENCRYPTED: + raise Refusal("package.zip.entry", "%s: encrypted entries are refused" % name) + top, sep, rest = name.partition("/") + if not sep or not K.DOCUMENT_KEY_RE.match(top): + raise Refusal("package.zip.entry", "%s: every entry sits under one folder named by the key" % name) + if folder is None: + folder = top + elif top != folder: + raise Refusal("package.zip.entry", "%s: entries sit under more than one top-level folder" % name) + if name in seen: + raise Refusal("package.zip.entry", "%s: duplicate entry" % name) + seen.add(name) + if zi.is_dir(): + if rest != "" and not safe_path(rest.rstrip("/")): + raise Refusal("package.zip.entry", "%s: unsafe path" % name) + continue + if stat.S_ISLNK(zi.external_attr >> 16): + raise Refusal("package.zip.entry", "%s: symbolic links are refused" % name) + if zi.compress_type not in (zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED): + raise Refusal("package.zip.entry", "%s: entries are stored or deflated" % name) + if rest != "MANIFEST.json" and not safe_path(rest): + raise Refusal("package.zip.entry", "%s: unsafe path" % name) + total += zi.file_size + if total > limit: + raise Refusal("package.zip.size", "the archive expands past the limit of %d bytes" % limit) + return folder + + +def read_zip(path, dest, limit=ZIP_LIMIT): + """Unpack a zipped package into the empty or new folder `dest`, refusing what spec/12 §12.2 refuses. + + Returns the package folder, `dest/<key>`. Every byte written is counted against each entry's declared size + and against `limit`, so a header that lies about a size is refused too. + """ + try: + zf = zipfile.ZipFile(path) + except (zipfile.BadZipFile, OSError) as e: + raise Refusal("package.zip.entry", "not a zip archive: %s" % e) + with zf: + folder = _zip_entries(zf, limit) + root = os.path.join(dest, folder) + os.makedirs(root) + written = 0 + for zi in zf.infolist(): + if zi.is_dir(): + continue + rest = zi.filename.partition("/")[2] + full = os.path.join(root, rest) + os.makedirs(os.path.dirname(full), exist_ok=True) + try: + with zf.open(zi) as src, open(full, "wb") as dst: + n = 0 + while True: + chunk = src.read(1 << 16) + if not chunk: + break + n += len(chunk) + written += len(chunk) + if n > zi.file_size or written > limit: + raise Refusal("package.zip.size", "%s: holds more than its header declares" % zi.filename) + dst.write(chunk) + except (zipfile.BadZipFile, RuntimeError, OSError) as e: + raise Refusal("package.zip.entry", "%s: %s" % (zi.filename, e)) + return root + + +def validate_zip(path, store, key=None, limit=ZIP_LIMIT): + """Validate a zipped package: unpack it under spec/12 §12.2's rules, then validate the folder.""" + with tempfile.TemporaryDirectory() as tmp: + try: + root = read_zip(path, tmp, limit) + except Refusal as e: + rep = Report() + rep.add(e.rule, e.node or "", e.message) + return rep + rep = validate(root, store, key) + mpath = os.path.join(root, "MANIFEST.json") + if os.path.exists(mpath): + try: + mkey = read_json(mpath).get("key") + except (Refusal, ValueError): + mkey = None + if mkey != os.path.basename(root): + rep.add("package.zip.entry", os.path.basename(root), "the top-level folder is not named by the key") + return rep diff --git a/tools/oracle/receipts.py b/tools/oracle/receipts.py new file mode 100644 index 0000000..05d9465 --- /dev/null +++ b/tools/oracle/receipts.py @@ -0,0 +1,284 @@ +"""Receipts, revocations, levels, spot-check sampling and reviewer error bounds. + +Non-normative; see spec/08-fidelity.md. +""" + +import base64 +import binascii +import hashlib +import math +from fractions import Fraction +from math import comb + +from . import crypto, jcs, mldsa, vrf +from .model import LEVELS +from .text import record_id, sha256_hex + +SIGNED_FORMATS = ("scienting-receipt/1", "scienting-revocation/1", "scienting-policy/1", "scienting-qa-report/1") + + +def record_hash(rec): + """SHA-256 of the canonical JSON of a signed record without its `id` and `signature`.""" + return sha256_hex(jcs.dumpb({k: v for k, v in rec.items() if k not in ("id", "signature")})) + + +def signing_payload(rec): + return jcs.dumpb({"format": rec["format"], "hash": record_hash(rec)}) + + +def seal(rec, secret, key_id): + """Fill in a record's root (for receipts), ID and Ed25519 signature.""" + rec = dict(rec) + if rec["format"] == "scienting-receipt/1": + rec["root"] = crypto.merkle_root(crypto.receipt_items(rec)) + rec.pop("id", None) + rec.pop("signature", None) + sig = crypto.ed25519_sign(secret, signing_payload(rec)) + rec["id"] = record_id(record_hash(rec)) + rec["signature"] = {"scheme": "ed25519", "key": key_id, "value": base64.b64encode(sig).decode("ascii")} + return rec + + +def _b64(s): + """Strict Base64 decoding; None for anything that is not Base64.""" + try: + return base64.b64decode(s, validate=True) + except (binascii.Error, ValueError, TypeError): + return None + + +def verify_signature(rec, roster): + """Whether the record's signature verifies under the roster key it names, for the schemes the tools implement + (`ed25519` and `ml-dsa-65`); any other scheme does not verify. Never raises.""" + sig = rec.get("signature") or {} + if not isinstance(sig, dict): + return False + key = roster.get(sig.get("key")) + if not key or sig.get("scheme") != key.get("scheme"): + return False + pub, value = _b64(key.get("public", "")), _b64(sig.get("value", "")) + if pub is None or value is None: + return False + try: + if sig["scheme"] == "ed25519": + return len(pub) == 32 and len(value) == 64 and crypto.ed25519_verify(pub, signing_payload(rec), value) + if sig["scheme"] == "ml-dsa-65": + return mldsa.verify(pub, signing_payload(rec), value) + except (ValueError, TypeError): + return False + return False + + +def seal_mldsa(rec, sk, key_id): + """Fill in a record's root (for receipts), ID and ML-DSA-65 signature, deterministically.""" + rec = dict(rec) + if rec["format"] == "scienting-receipt/1": + rec["root"] = crypto.merkle_root(crypto.receipt_items(rec)) + rec.pop("id", None) + rec.pop("signature", None) + sig = mldsa.sign(sk, signing_payload(rec)) + rec["id"] = record_id(record_hash(rec)) + rec["signature"] = {"scheme": "ml-dsa-65", "key": key_id, "value": base64.b64encode(sig).decode("ascii")} + return rec + + +def key_valid_at(key, at): + return key["registered_at"] <= at and (key.get("revoked_at") is None or at < key["revoked_at"]) + + +# --- spot-checks -------------------------------------------------------------- + + +def seed_payload(receipt): + return jcs.dumpb({"format": "scienting-spot-check/1", "receipt": record_hash(receipt)}) + + +def make_seed(receipt, checker_secret): + """The seed: the checker's VRF proof (RFC 9381, ECVRF-EDWARDS25519-SHA512-TAI) for the receipt's payload.""" + return vrf.prove(checker_secret, seed_payload(receipt)) + + +def sample_size(n, rate="0.05", minimum=10): + return min(n, max(minimum, math.ceil(Fraction(rate) * n))) + + +def sample(receipt, seed, rate="0.05", minimum=10): + """The sample a seed selects: ranked by SHA-256 of the proof's VRF output followed by the node ID.""" + beta = vrf.proof_to_hash(seed) + if beta is None: + raise ValueError("the seed is not a VRF proof") + ids = [nid for nid, _ in receipt["nodes"]] + m = sample_size(len(ids), rate, minimum) + ranked = sorted(ids, key=lambda nid: (hashlib.sha256(beta + nid.encode("utf-8")).hexdigest(), nid)) + return sorted(ranked[:m]) + + +def upper_bound(k, n, confidence="0.95"): + """One-sided Clopper-Pearson upper bound on an error rate, as a float.""" + if n <= 0: + raise ValueError("n must be positive") + if k >= n: + return 1.0 + alpha = 1.0 - float(Fraction(confidence)) + + def cdf(p): + if p <= 0: + return 1.0 + if p >= 1: + return 0.0 + lp, lq = math.log(p), math.log1p(-p) + total = 0.0 + for i in range(k + 1): + total += math.exp(math.lgamma(n + 1) - math.lgamma(i + 1) - math.lgamma(n - i + 1) + i * lp + + (n - i) * lq) + return total + + lo, hi = 0.0, 1.0 + for _ in range(200): + mid = (lo + hi) / 2 + if cdf(mid) > alpha: + lo = mid + else: + hi = mid + return hi + + +def bound_string(k, n, confidence="0.95"): + """The bound as the spec reports it: six decimal places, rounded up, computed exactly. + + The reported value is the least multiple of 10^-6 at which the probability of at most k errors in n is + at most 1 - c, found by bisection with integer arithmetic, so no floating point enters the result. + """ + if n <= 0: + raise ValueError("n must be positive") + if k >= n: + return "1.000000" + alpha = 1 - Fraction(confidence) + scale = 10**6 + + def tail_at_most(m): + # P[X <= k] at p = m / scale, compared with alpha, both scaled by scale**n and alpha's denominator. + total = sum(comb(n, i) * m**i * (scale - m)**(n - i) for i in range(k + 1)) + return total * alpha.denominator <= alpha.numerator * scale**n + + lo, hi = 0, scale # the tail at 0 is 1 (above alpha); at 1 it is 0 (k < n) + while hi - lo > 1: + mid = (lo + hi) // 2 + if tail_at_most(mid): + hi = mid + else: + lo = mid + return "%d.%06d" % (hi // scale, hi % scale) + + +# --- levels ------------------------------------------------------------------- + + +def revoked(receipt, revocations): + for r in revocations: + if r.get("receipt") == receipt["id"]: + return True + if r.get("signer") == receipt["by"] and r.get("period"): + p = r["period"] + if p["from"] <= receipt["at"] <= p["to"]: + return True + return False + + +def valid_revocations(revocations, receipts_by_id, roster): + """The revocations signed by the receipt's signer, the signer they name, or a key the roster makes an owner.""" + owners = {k for k, v in roster.items() if v.get("role") == "owner"} + out = [] + for r in revocations: + if not verify_signature(r, roster): + continue + signer = r["signature"]["key"] + allowed = set(owners) + if r.get("receipt") in receipts_by_id: + allowed.add(receipts_by_id[r["receipt"]]["by"]) + if r.get("signer"): + allowed.add(r["signer"]) + if signer in allowed: + out.append(r) + return out + + +def _base_status(rec, roster, valid_revs): + """`invalid`, `revoked` or `valid` for one receipt, before spot-checks are considered (spec/08 §8.6).""" + try: + if rec.get("root") != crypto.merkle_root(crypto.receipt_items(rec)): + return "invalid" + if rec["id"] != record_id(record_hash(rec)) or not verify_signature(rec, roster): + return "invalid" + key = roster.get(rec["by"]) + if not key or not key_valid_at(key, rec["at"]) or rec["signature"]["key"] != rec["by"]: + return "invalid" + except (KeyError, TypeError, ValueError): + return "invalid" + return "revoked" if revoked(rec, valid_revs) else "valid" + + +def statuses(records, roster): + """The status of every receipt in `records` (spec/08 §8.6), computed once. + + A receipt is suspended when a valid spot-check of it found an error, and a spot-check's own validity may + depend on its own spot-check, so statuses are settled from the end of each chain of spot-checks; a chain + that loops back on itself settles nothing, and its receipts are invalid. + """ + receipts = [x for x in records if x.get("format") == "scienting-receipt/1"] + revs = [x for x in records if x.get("format") == "scienting-revocation/1"] + by_id = {x["id"]: x for x in receipts} + valid_revs = valid_revocations(revs, by_id, roster) + base = {rec["id"]: _base_status(rec, roster, valid_revs) for rec in receipts} + checkers = {} + for q in receipts: + qa = q.get("qa") + if isinstance(qa, dict) and qa.get("errors") and base.get(q["id"]) == "valid" and qa.get("of") in by_id: + checkers.setdefault(qa["of"], []).append(q["id"]) + final = {rid: s for rid, s in base.items() if s != "valid" or rid not in checkers} + pending = set(base) - set(final) + progress = True + while pending and progress: + progress = False + for rid in sorted(pending): + qs = checkers[rid] + if all(q in final for q in qs): + final[rid] = "suspended" if any(final[q] == "valid" for q in qs) else "valid" + pending.discard(rid) + progress = True + for rid in pending: + final[rid] = "invalid" + return final + + +def receipt_status(rec, records, roster): + """`valid`, `revoked`, `suspended`, or `invalid` for one receipt among `records`.""" + return statuses(records, roster).get(rec.get("id"), "invalid") + + +def effective_levels(nodes, values, records, roster): + """Every leaf's level: its recorded level, raised by valid receipts that list it at its current hash. + + A spot-check's `qa:` receipt does not raise the nodes it found in error (spec/08 §8.2). + """ + level = {n["id"]: n.get("fidelity") for n in nodes if "fidelity" in n} + status = statuses(records, roster) + for rec in records: + if rec["format"] != "scienting-receipt/1": + continue + if status.get(rec["id"]) != "valid": + continue + wrong = {e["node"] for e in (rec.get("qa") or {}).get("errors", [])} + for nid, h in rec.get("nodes", []): + if nid in level and nid not in wrong and values[nid]["node_hash"] == h: + if LEVELS.index(rec["level"]) > LEVELS.index(level[nid]): + level[nid] = rec["level"] + return level + + +def distribution(levels): + counts = {lv: 0 for lv in LEVELS} + for lv in levels.values(): + counts[lv] += 1 + lowest = next((lv for lv in LEVELS if counts[lv]), None) + return {"lowest": lowest, "counts": counts} diff --git a/tools/oracle/rights.py b/tools/oracle/rights.py new file mode 100644 index 0000000..9d9a3bb --- /dev/null +++ b/tools/oracle/rights.py @@ -0,0 +1,106 @@ +"""Rights records, policies, stage checks and backend conditions. + +Non-normative; see spec/14-rights.md. +""" + +USES = ("read", "tdm", "redistribute", "quote-public", "accessible-copy") +PURPOSES = ("internal", "external") +PROCESSORS = ("local", "tenancy", "outside-no-retention", "outside") +AI_PAIRS = tuple(p + "/" + q for p in PURPOSES for q in PROCESSORS) + + +def _value(v): + return v if v in (True, False) else "unknown" + + +def flat(rights): + """A rights record's uses as one flat map: the five uses plus ai/<purpose>/<processor>.""" + uses = rights.get("uses", {}) + out = {u: _value(uses.get(u, "unknown")) for u in USES} + ai = uses.get("ai", {}) + for pair in AI_PAIRS: + out["ai/" + pair] = _value(ai.get(pair, "unknown")) + return out + + +def _policy_applies(policy, witness, now): + if policy.get("valid_until") and now >= policy["valid_until"]: + return False + if policy.get("at") and now < policy["at"]: + return False + a = policy.get("applies_to", {}) + r = witness["rights"] + if "basis" in a and r.get("basis") not in a["basis"]: + return False + if "license" in a and (r.get("license") or {}).get("spdx") not in a["license"]: + return False + if "doi_prefixes" in a: + doi = (witness.get("origin") or {}).get("doi") or "" + if not any(doi.startswith(p) for p in a["doi_prefixes"]): + return False + if "witnesses" in a and witness["sha256"] not in a["witnesses"]: + return False + return True + + +def effective(witness, policies, now): + """The witness's uses at `now`, with unknowns resolved by applicable policies, or all false if expired.""" + r = witness["rights"] + f = flat(r) + if r.get("valid_until") and now >= r["valid_until"]: + return {k: False for k in f}, True + for p in policies: + if not _policy_applies(p, witness, now): + continue + pf = flat({"uses": p.get("uses", {})}) + for k, v in pf.items(): + if f[k] == "unknown" and v != "unknown": + f[k] = v + return f, False + + +def combine(flats): + """The most restrictive of several witnesses' uses: false over unknown over true.""" + out = {} + for k in flats[0]: + vals = [f[k] for f in flats] + out[k] = False if False in vals else ("unknown" if "unknown" in vals else True) + return out + + +def check(stage, processor, uses): + """Whether a stage may run on a processor under `uses`. Returns (allowed, lacking).""" + lacking = [] + for u in stage.get("uses", []): + if uses[u] is not True: + lacking.append(u if uses[u] is False else u + "?") + ai = stage.get("ai") + if ai: + allowed_here = ai.get("processors") + if allowed_here and processor not in allowed_here: + lacking.append("processor:" + processor) + k = "ai/" + ai["purpose"] + "/" + processor + if uses[k] is not True: + lacking.append(k if uses[k] is False else k + "?") + return (not lacking), lacking + + +def backend_allowed(backend, profile): + """Whether a team profile meets every condition a backend's licenses impose. Returns (ok, failed).""" + failed = [] + for cond in backend.get("conditions", []): + k = cond["kind"] + if k == "revenue-cap": + r = profile.get("revenue_or_funding_usd") + if r is None or r.get("at_most") is None or r["at_most"] > cond["usd"]: + failed.append(cond["id"]) + elif k == "no-competition": + comp = profile.get("competes_with") + if comp is None or cond["vendor"] in comp: + failed.append(cond["id"]) + elif k == "purpose": + if profile.get("purpose") not in cond["allowed"]: + failed.append(cond["id"]) + else: + failed.append(cond["id"]) + return (not failed), failed diff --git a/tools/oracle/schema.py b/tools/oracle/schema.py new file mode 100644 index 0000000..7bba4b8 --- /dev/null +++ b/tools/oracle/schema.py @@ -0,0 +1,89 @@ +"""JSON Schema (draft 2020-12) validation with the `jsonschema` package, and the lint of the keyword subset. + +Non-normative. +The spec's schemas are restricted to the keywords below (spec/22-conformance.md) so that every 2020-12 +validator reads them alike; `lint` refuses any schema that leaves the subset. +""" + +import json +import os + +from jsonschema import Draft202012Validator +from referencing import Registry, Resource + +KEYWORDS = { + "$schema", "$id", "$ref", "$defs", "$comment", "title", "description", "examples", "default", "deprecated", + "type", "enum", "const", "properties", "required", "additionalProperties", "patternProperties", + "propertyNames", "minProperties", "maxProperties", "dependentRequired", "items", "prefixItems", "minItems", + "maxItems", "uniqueItems", "contains", "minLength", "maxLength", "pattern", "format", "minimum", "maximum", + "exclusiveMinimum", "exclusiveMaximum", "oneOf", "anyOf", "allOf", "not", "if", "then", "else", +} +FORBIDDEN_PATTERN_TOKENS = ("\\d", "\\w", "\\s", "\\b", "\\D", "\\W", "\\S", "\\B", "(?<", "(?P") + + +class SchemaError(Exception): + pass + + +class Store: + """The schemas of one folder, linted on load, with a compiled validator per schema.""" + + def __init__(self, root): + self.root = root + self.docs = {} + self._registry = None + self._validators = {} + + def registry(self): + if self._registry is None: + names = sorted(f for f in os.listdir(self.root) if f.endswith(".schema.json")) + self._registry = Registry().with_resources( + [(self.load(f)["$id"], Resource.from_contents(self.load(f))) for f in names]) + return self._registry + + def validator(self, name): + if name not in self._validators: + self._validators[name] = Draft202012Validator(self.load(name), registry=self.registry()) + return self._validators[name] + + def load(self, name): + if name not in self.docs: + with open(os.path.join(self.root, name), encoding="utf-8") as f: + self.docs[name] = json.load(f) + lint(self.docs[name], name) + return self.docs[name] + + def deref(self, base, ref): + name, _, frag = ref.partition("#") + name = name or base + node = self.load(name) + if frag: + for part in frag.lstrip("/").split("/"): + node = node[part.replace("~1", "/").replace("~0", "~")] + return name, node + + +def lint(schema, where): + """Refuse keywords outside the subset, and regex syntax that differs between dialects.""" + if isinstance(schema, dict): + for k, v in schema.items(): + if k not in KEYWORDS: + raise SchemaError("%s: keyword %s is outside the subset" % (where, k)) + if k == "pattern" and any(t in v for t in FORBIDDEN_PATTERN_TOKENS): + raise SchemaError("%s: pattern %r uses dialect-dependent syntax" % (where, v)) + if k in ("properties", "patternProperties", "$defs"): + for kk, vv in v.items(): + if k == "patternProperties" and any(t in kk for t in FORBIDDEN_PATTERN_TOKENS): + raise SchemaError("%s: pattern %r uses dialect-dependent syntax" % (where, kk)) + lint(vv, where + "/" + kk) + elif k in ("items", "additionalProperties", "propertyNames", "not", "if", "then", "else", "contains"): + lint(v, where + "/" + k) + elif k in ("oneOf", "anyOf", "allOf", "prefixItems"): + for i, s in enumerate(v): + lint(s, "%s/%s/%d" % (where, k, i)) + + +def validate(store, name, instance): + """Return a list of error strings, `path: message`, in path order; empty when the instance is valid.""" + errors = sorted(store.validator(name).iter_errors(instance), key=lambda e: [str(x) for x in e.absolute_path]) + return ["%s: %s" % ("/" + "/".join(str(x) for x in e.absolute_path), e.message) for e in errors] diff --git a/tools/oracle/targets.py b/tools/oracle/targets.py new file mode 100644 index 0000000..007fada --- /dev/null +++ b/tools/oracle/targets.py @@ -0,0 +1,69 @@ +"""The target set of targeted F3: the nodes a team's claims, data and quotations rest on. + +Non-normative; see spec/08-fidelity.md §8.10. +""" + +from .model import LEAVES, MATH_KINDS +from .text import is_digit + +DIGIT_RULES = ("all", "anchored-sections", "none") +# The kinds that count as the section a node sits in: a section, or the front or back matter outside any. +SECTION_KINDS = frozenset(["section", "front", "back"]) +DIGIT_KINDS = frozenset(["sentence", "cell"]) +DIGIT_RUNS = frozenset(["text", "math"]) + + +def has_digit_run(node): + """Whether a `text` or `math` run of the node holds a digit (General Category Nd).""" + for r in node.get("content") or []: + if not isinstance(r, dict) or r.get("kind") not in DIGIT_RUNS: + continue + s = r.get("text") if r["kind"] == "text" else r.get("source") + if any(is_digit(ch) for ch in s or ""): + return True + return False + + +def enclosing_section(doc, nid): + """The nearest ancestor-or-self that is a section, or the front or back matter, else the root.""" + if doc.nodes[nid]["kind"] in SECTION_KINDS: + return nid + for a in reversed(doc.ancestors(nid)): + if doc.nodes[a]["kind"] in SECTION_KINDS: + return a + return doc.root + + +def target_set(doc, anchored, digit_rule="all"): + """The target set as `[[node, reason], …]` in document order, with `reason` the first that applies of + `anchored`, `equation` and `digits`. + + `anchored` lists the live nodes that extracts, dataset values, confirmed claim links, draft quotations or + pinned citations anchor; a container among them contributes its leaves. Every equation and equation line + is a target. Under `all`, so is every sentence or cell with a digit in a text or math run; under + `anchored-sections`, only those in a section that holds an anchored node; under `none`, none. + """ + if digit_rule not in DIGIT_RULES: + raise ValueError("digit rule must be one of %s" % ", ".join(DIGIT_RULES)) + anchored = set(anchored) + unknown = sorted(a for a in anchored if a not in doc.nodes) + if unknown: + raise ValueError("anchored nodes are not live: %s" % ", ".join(unknown)) + reasons = {} + for nid in sorted(anchored): + if doc.nodes[nid]["kind"] in LEAVES: + reasons[nid] = "anchored" + else: + for leaf in doc.leaves(nid): + reasons.setdefault(leaf, "anchored") + for nid in doc.preorder(): + if doc.nodes[nid]["kind"] in MATH_KINDS: + reasons.setdefault(nid, "equation") + if digit_rule != "none": + sections = {enclosing_section(doc, a) for a in anchored} + for nid in doc.preorder(): + n = doc.nodes[nid] + if n["kind"] in DIGIT_KINDS and has_digit_run(n): + if digit_rule == "all" or enclosing_section(doc, nid) in sections: + reasons.setdefault(nid, "digits") + return [[nid, reasons[nid]] for nid in doc.preorder() if nid in reasons] diff --git a/tools/oracle/text.py b/tools/oracle/text.py new file mode 100644 index 0000000..1c3ef85 --- /dev/null +++ b/tools/oracle/text.py @@ -0,0 +1,105 @@ +"""Text normalization, IDs, keys and small shared helpers. + +Non-normative; see spec/01-conventions.md and spec/04-identity.md. +""" + +import hashlib +import re +import unicodedata + +from . import jcs + +# Unicode White_Space=yes (PropList.txt), the set every rule in the spec means by "whitespace". +WHITE_SPACE = frozenset( + [0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x20, 0x85, 0xA0, 0x1680] + + list(range(0x2000, 0x200B)) + + [0x2028, 0x2029, 0x202F, 0x205F, 0x3000] +) + + +def is_ws(ch): + return ord(ch) in WHITE_SPACE + + +def collapse_ws(s): + out = [] + prev_ws = False + for ch in s: + if is_ws(ch): + if not prev_ws: + out.append(" ") + prev_ws = True + else: + out.append(ch) + prev_ws = False + return "".join(out) + + +def trim(s): + a, b = 0, len(s) + while a < b and is_ws(s[a]): + a += 1 + while b > a and is_ws(s[b - 1]): + b -= 1 + return s[a:b] + + +def remove_ws(s): + return "".join(ch for ch in s if not is_ws(ch)) + + +def norm(s): + """The hashing normalization: NFC, whitespace runs to one U+0020, trimmed.""" + return trim(collapse_ws(unicodedata.normalize("NFC", s))) + + +def sha256_hex(b): + if isinstance(b, str): + b = b.encode("utf-8") + return hashlib.sha256(b).hexdigest() + + +def is_digit(ch): + return unicodedata.category(ch) == "Nd" + + +def digits(s): + return "".join(ch for ch in s if is_digit(ch)) + + +# Crockford base32, lowercase. +ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz" +LETTERS = "abcdefghjkmnpqrstvwxyz" +assert len(ALPHABET) == 32 and len(LETTERS) == 22 + +NODE_ID_RE = re.compile(r"^[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6}$") +RECORD_ID_RE = re.compile(r"^[a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]{6,25}$") +KEY_RE = re.compile(r"^[a-z0-9][a-z0-9._-]*$") +HASH_RE = re.compile(r"^[0-9a-f]{64}$") + + +def letter_first(digest, length): + """Encode a digest as a letter-first Crockford base32 ID of `length` characters.""" + first = LETTERS[digest[0] % 22] + bits = int.from_bytes(digest[1:], "big") + nbits = 8 * (len(digest) - 1) + out = [first] + for i in range(length - 1): + shift = nbits - 5 * (i + 1) + out.append(ALPHABET[(bits >> shift) & 31]) + return "".join(out) + + +def mint_node_id(doc_key, kind, text_hash, occurrence): + d = hashlib.sha256(jcs.dumpb(["scienting-id/1", doc_key, kind, text_hash, occurrence])).digest() + return letter_first(d, 7) + + +def record_id(record_hash_hex): + """A record's ID: 13 letter-first base32 characters of its record hash.""" + return letter_first(bytes.fromhex(record_hash_hex), 13) + + +def cp_to_utf16(s, offset): + """Convert a code point offset in `s` to a UTF-16 code unit offset.""" + return sum(2 if ord(ch) > 0xFFFF else 1 for ch in s[:offset]) diff --git a/tools/oracle/tree.py b/tools/oracle/tree.py new file mode 100644 index 0000000..f4a1fa8 --- /dev/null +++ b/tools/oracle/tree.py @@ -0,0 +1,249 @@ +"""Establishing a document from a nested tree, minting IDs, and structural checks. + +Non-normative; see spec/03-nodes.md and spec/04-identity.md. +""" + +import copy + +from . import hashing +from .model import ( + AT_MOST_ONCE, CHILDREN, KINDS, LABELLED, LEAVES, MATH_KINDS, NONEMPTY, RUN_KINDS, RUNS, STYLES, + VERBATIM_KINDS, Doc, +) +from .text import NODE_ID_RE, mint_node_id, norm + + +class Refusal(Exception): + """A rule was broken. `rule` names it, as spec/22-conformance.md lists.""" + + def __init__(self, rule, message, node=None): + super().__init__("%s: %s" % (rule, message)) + self.rule = rule + self.message = message + self.node = node + + +def canonical_runs(runs): + """Drop empty text runs and join adjacent text runs with the same styles.""" + out = [] + for r in runs: + r = dict(r) + if r["kind"] == "text": + if "style" in r: + r["style"] = sorted(set(r["style"])) + if not r["style"]: + del r["style"] + if r["text"] == "": + continue + if out and out[-1]["kind"] == "text" and out[-1].get("style") == r.get("style"): + out[-1] = dict(out[-1], text=out[-1]["text"] + r["text"]) + continue + out.append(r) + return out + + +def _flatten(spec, parent, ord_, out): + node = {k: v for k, v in spec.items() if k != "children"} + node["_parent"] = parent + node["ord"] = ord_ + out.append(node) + idx = len(out) - 1 + for i, c in enumerate(spec.get("children", [])): + _flatten(c, idx, i, out) + return idx + + +def mint_ids(doc_key, flat, used, preassigned=None): + """Mint IDs for flat nodes in document order. `flat` nodes carry `_parent` indices.""" + preassigned = preassigned or {} + tmp = [] + for i, n in enumerate(flat): + m = {k: v for k, v in n.items() if not k.startswith("_")} + m["id"] = "tmp%d" % i + m["parent"] = None if n["_parent"] is None else "tmp%d" % n["_parent"] + tmp.append(m) + _resolve_child_refs(tmp) + doc = Doc(doc_key, tmp) + seen = {} + ids = {} + for i, n in enumerate(tmp): + if i in preassigned: + ids[n["id"]] = preassigned[i] + used.add(preassigned[i]) + continue + th = hashing.PLAIN(norm(hashing.plain(doc, n["id"]))) + k = (n["kind"], th) + occ = seen.get(k, 0) + seen[k] = occ + 1 + nid = mint_node_id(doc_key, n["kind"], th, occ) + while nid in used: + occ += 1 + nid = mint_node_id(doc_key, n["kind"], th, occ) + used.add(nid) + ids[n["id"]] = nid + result = [] + for n in tmp: + m = dict(n) + m["id"] = ids[n["id"]] + m["parent"] = None if n["parent"] is None else ids[n["parent"]] + if m["kind"] in RUN_KINDS: + m["content"] = [ + dict(r, node=ids[r["node"]]) if r["kind"] == "equation" else r for r in m["content"] + ] + result.append(m) + return result + + +def _resolve_child_refs(tmp): + """Equation runs in a spec name their child by position: {"kind": "equation", "child": i}.""" + by_parent = {} + for n in tmp: + by_parent.setdefault(n["parent"], []).append(n) + for n in tmp: + if n["kind"] in RUN_KINDS: + kids = sorted(by_parent.get(n["id"], []), key=lambda c: c["ord"]) + runs = [] + for r in n["content"]: + if r["kind"] == "equation" and "child" in r: + r = {"kind": "equation", "node": kids[r["child"]]["id"]} + runs.append(r) + n["content"] = canonical_runs(runs) + + +def establish(doc_key, spec, used=None): + """Turn a nested spec into flat node records with minted IDs, in document order.""" + flat = [] + _flatten(copy.deepcopy(spec), None, 0, flat) + return mint_ids(doc_key, flat, used if used is not None else set()) + + +def with_values(doc_key, nodes, hasher=hashing.PLAIN): + doc = Doc(doc_key, nodes) + vals = hashing.compute(doc, hasher) + out = [] + for nid in doc.preorder(): + n = dict(doc.nodes[nid]) + for k in ("text_hash", "match_hash", "align_key", "own_hash", "node_hash"): + n.pop(k, None) + n.update(vals[nid]) + out.append(n) + return out + + +def validate_structure(doc): + """Check the tree against the child rules of spec/03-nodes.md.""" + if doc.root is None: + raise Refusal("doc.tree.root", "no root node") + roots = [x for x in doc.order if doc.nodes[x].get("parent") is None] + if len(roots) != 1 or doc.nodes[doc.root]["kind"] != "document": + raise Refusal("doc.tree.root", "exactly one root, of kind document, is required") + if doc.preorder() != doc.order: + raise Refusal("doc.tree.order", "nodes are not in document order") + seen = set() + for nid in doc.order: + n = doc.nodes[nid] + if nid in seen: + raise Refusal("doc.id.unique", "duplicate ID " + nid, nid) + seen.add(nid) + if not NODE_ID_RE.match(nid): + raise Refusal("doc.id.form", "ID is not seven letter-first base32 characters", nid) + k = n["kind"] + if k not in KINDS: + raise Refusal("doc.node.kind", "unknown kind " + k, nid) + kids = doc.kids(nid) + if [doc.nodes[c]["ord"] for c in kids] != list(range(len(kids))): + raise Refusal("doc.tree.ord", "child order is not 0..n-1", nid) + counts = {} + for i, c in enumerate(kids): + ck = doc.nodes[c]["kind"] + if ck not in CHILDREN[k]: + raise Refusal("doc.tree.child", "%s may not contain %s" % (k, ck), c) + counts[ck] = counts.get(ck, 0) + 1 + if ck == "heading" and i != 0: + raise Refusal("doc.tree.child", "a heading must be a section's first child", c) + for ck, cnt in counts.items(): + if cnt > 1 and (ck in AT_MOST_ONCE or ck == "heading"): + raise Refusal("doc.tree.child", "%s may occur once in %s" % (ck, k), nid) + if k == "table" and counts.get("table-body", 0) != 1: + raise Refusal("doc.tree.child", "a table has exactly one table-body", nid) + if k in NONEMPTY and not kids: + raise Refusal("doc.tree.empty", "%s must have children" % k, nid) + if n.get("label") is not None and k not in LABELLED: + raise Refusal("doc.node.label", "%s does not take a label" % k, nid) + _check_content(doc, nid) + + +def _check_content(doc, nid): + n = doc.nodes[nid] + k = n["kind"] + if n.get("withheld"): + if "content" in n: + raise Refusal("doc.policy.withheld", "a withheld node keeps no content", nid) + return + if k in RUN_KINDS: + runs = n.get("content") + if not isinstance(runs, list) or not runs: + raise Refusal("doc.node.content", "runs are required", nid) + if canonical_runs(runs) != runs: + raise Refusal("doc.run.canonical", "runs are not in canonical form", nid) + eq_refs = [] + for r in runs: + if r["kind"] not in RUNS: + raise Refusal("doc.run.kind", "unknown run kind " + r["kind"], nid) + st = r.get("style", []) + if any(s not in STYLES for s in st) or ("sup" in st and "sub" in st): + raise Refusal("doc.run.style", "bad style set", nid) + if r["kind"] == "equation": + eq_refs.append(r["node"]) + kids = doc.kids(nid) + if eq_refs != kids: + raise Refusal("doc.run.equation", "equation runs must name the sentence's children in order", nid) + elif k in MATH_KINDS: + c = n.get("content") or {} + if c.get("notation") not in ("tex", "typst") or not isinstance(c.get("source"), str): + raise Refusal("doc.node.content", "equations need a notation and a source", nid) + elif k in VERBATIM_KINDS: + c = n.get("content") or {} + if not isinstance(c.get("text"), str): + raise Refusal("doc.node.content", "verbatim nodes need text", nid) + elif "content" in n: + raise Refusal("doc.node.content", "%s holds no content" % k, nid) + if k == "section" and not isinstance(n.get("attrs", {}).get("level"), int): + raise Refusal("doc.node.attrs", "a section needs a level", nid) + + +def validate_references(doc): + """Check the references between nodes: cite, fnmark and xref runs, and the header paths of tables and rows + (spec/03 §3.4–3.5, spec/09 §9.2). Raises Refusal.""" + kinds = {nid: doc.nodes[nid]["kind"] for nid in doc.order} + for nid in doc.order: + n = doc.nodes[nid] + if n["kind"] in RUN_KINDS and not n.get("withheld"): + for r in n.get("content") or []: + if r["kind"] == "cite": + for ref in r["refs"]: + if kinds.get(ref) != "reference": + raise Refusal("doc.run.cite", "cite names %s, which is not a reference" % ref, nid) + if r["kind"] == "fnmark" and r.get("footnote") is not None and kinds.get(r["footnote"]) != "footnote": + raise Refusal("doc.run.fnmark", "fnmark names a node that is not a footnote", nid) + if r["kind"] == "xref" and r.get("target") and "#" not in r["target"] and r["target"] not in kinds: + raise Refusal("doc.run.xref", "xref names no node in this document", nid) + if n["kind"] == "table": + for col in n.get("attrs", {}).get("columns", []): + for h in col["header_path"]: + if kinds.get(h) != "cell": + raise Refusal("doc.table.header", "a header path names %s, not a cell" % h, nid) + if n["kind"] == "row": + for h in n.get("attrs", {}).get("header_path", []): + if kinds.get(h) != "cell": + raise Refusal("doc.table.header", "a row header path names %s, not a cell" % h, nid) + if n["kind"] == "cell": + col = n.get("attrs", {}).get("column") + table = next((a for a in reversed(doc.ancestors(nid)) if kinds[a] == "table"), None) + columns = {c["id"] for c in doc.nodes[table].get("attrs", {}).get("columns", [])} if table else set() + if col is not None and columns and col not in columns: + raise Refusal("doc.table.header", "a cell names a column its table does not define", nid) + + +def leaf_kinds(): + return LEAVES diff --git a/tools/oracle/vrf.py b/tools/oracle/vrf.py new file mode 100644 index 0000000..da9d695 --- /dev/null +++ b/tools/oracle/vrf.py @@ -0,0 +1,179 @@ +"""ECVRF-EDWARDS25519-SHA512-TAI, the verifiable random function of RFC 9381 over the Ed25519 curve. + +Non-normative; see spec/08-fidelity.md §8.8. +A VRF proof has exactly one valid value for a key and an input, where an Ed25519 signature has many, so a +spot-check seed that is a VRF proof cannot be ground by the checker. The arithmetic is the reference form of +RFC 8032 in plain Python, slow and clear; the keys are ordinary Ed25519 keys, so the roster needs nothing new. +The RFC's Example 16 is pinned in vectors/vrf.jsonl. +""" + +import hashlib + +SUITE = b"\x03" +COFACTOR = 8 +P = 2**255 - 19 +Q = 2**252 + 27742317777372353535851937790883648493 +D = (-121665 * pow(121666, P - 2, P)) % P +_I = pow(2, (P - 1) // 4, P) + + +def _inv(x): + return pow(x, P - 2, P) + + +def _recover_x(y, sign): + if y >= P: + return None + x2 = (y * y - 1) * _inv(D * y * y + 1) % P + if x2 == 0: + return None if sign else 0 + x = pow(x2, (P + 3) // 8, P) + if (x * x - x2) % P != 0: + x = x * _I % P + if (x * x - x2) % P != 0: + return None + if (x & 1) != sign: + x = P - x + return x + + +# Points in extended homogeneous coordinates (X, Y, Z, T) with x = X/Z, y = Y/Z, x*y = T/Z (RFC 8032 §5.1.4). +G_Y = 4 * _inv(5) % P +G_X = _recover_x(G_Y, 0) +G = (G_X, G_Y, 1, G_X * G_Y % P) +IDENTITY = (0, 1, 1, 0) + + +def _add(a, b): + x1, y1, z1, t1 = a + x2, y2, z2, t2 = b + A = (y1 - x1) * (y2 - x2) % P + B = (y1 + x1) * (y2 + x2) % P + C = t1 * 2 * D * t2 % P + Dd = z1 * 2 * z2 % P + E, F, Gg, H = B - A, Dd - C, Dd + C, B + A + return (E * F % P, Gg * H % P, F * Gg % P, E * H % P) + + +def _mul(s, pt): + out, acc = IDENTITY, pt + while s > 0: + if s & 1: + out = _add(out, acc) + acc = _add(acc, acc) + s >>= 1 + return out + + +def _equal(a, b): + return (a[0] * b[2] - b[0] * a[2]) % P == 0 and (a[1] * b[2] - b[1] * a[2]) % P == 0 + + +def point_to_string(pt): + z = _inv(pt[2]) + x, y = pt[0] * z % P, pt[1] * z % P + return (y | ((x & 1) << 255)).to_bytes(32, "little") + + +def string_to_point(s): + """The point a 32-byte string encodes, or None when it is not a valid encoding (RFC 8032 §5.1.3).""" + if len(s) != 32: + return None + y = int.from_bytes(s, "little") + sign = y >> 255 + y &= (1 << 255) - 1 + x = _recover_x(y, sign) + if x is None: + return None + return (x, y, 1, x * y % P) + + +def _secret_scalar(sk): + h = hashlib.sha512(sk).digest() + a = bytearray(h[:32]) + a[0] &= 248 + a[31] &= 63 + a[31] |= 64 + return int.from_bytes(a, "little"), h[32:] + + +def public_key(sk): + x, _ = _secret_scalar(sk) + return point_to_string(_mul(x, G)) + + +def encode_to_curve(pk_string, alpha): + """ECVRF_encode_to_curve_try_and_increment (RFC 9381 §5.4.1.1).""" + for ctr in range(256): + h = hashlib.sha512(SUITE + b"\x01" + pk_string + alpha + bytes([ctr]) + b"\x00").digest() + pt = string_to_point(h[:32]) + if pt is not None: + pt = _mul(COFACTOR, pt) + if not _equal(pt, IDENTITY): + return pt + raise ValueError("no curve point found") + + +def _challenge(points): + """ECVRF_challenge_generation (RFC 9381 §5.4.3): the first 16 octets of the hash, as a little-endian integer.""" + s = SUITE + b"\x02" + b"".join(point_to_string(p) for p in points) + b"\x00" + return int.from_bytes(hashlib.sha512(s).digest()[:16], "little") + + +def prove(sk, alpha): + """ECVRF_prove: the 80-byte proof Gamma || c || s for the 32-byte Ed25519 secret `sk` and input `alpha`.""" + x, suffix = _secret_scalar(sk) + y = _mul(x, G) + h = encode_to_curve(point_to_string(y), alpha) + h_string = point_to_string(h) + gamma = _mul(x, h) + k = int.from_bytes(hashlib.sha512(suffix + h_string).digest(), "little") % Q + c = _challenge([y, h, gamma, _mul(k, G), _mul(k, h)]) + s = (k + c * x) % Q + return point_to_string(gamma) + c.to_bytes(16, "little") + s.to_bytes(32, "little") + + +def decode_proof(pi): + if len(pi) != 80: + return None + gamma = string_to_point(pi[:32]) + if gamma is None: + return None + c = int.from_bytes(pi[32:48], "little") + s = int.from_bytes(pi[48:80], "little") + if s >= Q: + return None + return gamma, c, s + + +def proof_to_hash(pi): + """ECVRF_proof_to_hash: the 64-byte output beta of a proof (RFC 9381 §5.2), or None for a malformed proof.""" + d = decode_proof(pi) + if d is None: + return None + gamma = d[0] + return hashlib.sha512(SUITE + b"\x03" + point_to_string(_mul(COFACTOR, gamma)) + b"\x00").digest() + + +def _neg(pt): + return ((-pt[0]) % P, pt[1], pt[2], (-pt[3]) % P) + + +def verify(pk_string, alpha, pi): + """ECVRF_verify: beta when `pi` is the proof for `alpha` under the public key, else None. Never raises.""" + try: + y = string_to_point(pk_string) + if y is None or _equal(_mul(COFACTOR, y), IDENTITY): + return None + d = decode_proof(pi) + if d is None: + return None + gamma, c, s = d + h = encode_to_curve(pk_string, alpha) + u = _add(_mul(s, G), _neg(_mul(c, y))) + v = _add(_mul(s, h), _neg(_mul(c, gamma))) + if _challenge([y, h, gamma, u, v]) != c: + return None + return proof_to_hash(pi) + except (ValueError, TypeError): + return None diff --git a/tools/site.py b/tools/site.py new file mode 100644 index 0000000..841ee00 --- /dev/null +++ b/tools/site.py @@ -0,0 +1,636 @@ +#!/usr/bin/env python3 +"""Build the paperspec website: every file of the repository, and its Markdown rendered as documentation. + +Non-normative tooling, standard library only. +Usage: python3 tools/site.py [--out DIR] [--base-url URL] +The output folder (default `_site/`) mirrors the repository, so each file is served at its own path: a schema at +the URL in its `$id`, the JSON-LD context at the address layers name, and every vector, fixture and table as it is. +Beside each Markdown file the builder writes a page, `README.md` becoming its folder's `index.html` and `X.md` +becoming `X.html`; a folder with no README gets a listing. It also writes the vocabulary page that the context's +term IRIs point at, a search index, a 404 page and one stylesheet. Links between Markdown files are rewritten to +the pages, so the site works from any host, and `deploy/Caddyfile` serves it with the right media types. +""" + +import argparse +import html +import json +import os +import re +import shutil +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +SKIP_DIRS = {".git", ".pixi", ".claude", "_site", "__pycache__", "node_modules", ".gitea", ".vscode", ".idea"} +SKIP_FILES = {".DS_Store"} +NAME = "paperspec" +REPO = "https://git.scient.ing/infra/paperspec" +BASE_URL = "https://paperspec.scient.ing" + + +def version(): + with open(os.path.join(ROOT, "CHANGELOG.md"), encoding="utf-8") as f: + m = re.search(r"^## (\S+)", f.read(), re.M) + return m.group(1) if m else "unreleased" + + +# --- inline Markdown ------------------------------------------------------------------------------------------ + +def slug(heading): + """A heading's anchor as GitHub, Gitea and Forgejo compute it (the same rule tools/check.py uses).""" + t = re.sub(r"[`*]", "", heading.strip().lower()) + t = "".join(ch for ch in t if ch.isalnum() or ch in " -_") + return t.replace(" ", "-") + + +def rewrite_href(target): + """A Markdown link target as a site link: `X.md` becomes `X.html`, `README.md` its folder.""" + if re.match(r"^[a-z][a-z0-9+.-]*:", target) or target.startswith(("/", "#")): + return target + path, hashmark, frag = target.partition("#") + if path.endswith(".md"): + head, base = os.path.split(path) + if base == "README.md": + path = (head + "/") if head else "./" + else: + path = path[:-3] + ".html" + return path + hashmark + frag + + +def inline(text): + """Render the inline Markdown the documentation uses: code spans, autolinks, links, strong and emphasis.""" + stash = [] + + def keep(s): + stash.append(s) + return "\x00%d\x00" % (len(stash) - 1) + + text = re.sub(r"(`+)(.+?)\1", lambda m: keep("<code>%s</code>" % html.escape(m.group(2).strip(), quote=False)), text) + text = re.sub(r"<(https?://[^>\s]+)>", + lambda m: keep('<a href="%s">%s</a>' % (html.escape(m.group(1)), html.escape(m.group(1)))), text) + text = html.escape(text, quote=False) + + def link(m): + label, target = m.group(1), html.unescape(m.group(2)) + return keep('<a href="%s">%s</a>' % (html.escape(rewrite_href(target)), emphasis(label))) + + text = re.sub(r"\[([^\]]+)\]\(([^)\s]+)\)", link, text) + text = emphasis(text) + while "\x00" in text: + text = re.sub(r"\x00(\d+)\x00", lambda m: stash[int(m.group(1))], text) + return text + + +def emphasis(text): + text = re.sub(r"\*\*(?=\S)(.+?)(?<=\S)\*\*", r"<strong>\1</strong>", text) + return re.sub(r"(?<![\w*])\*(?=[^\s*])(.+?)(?<=[^\s*])\*(?![\w*])", r"<em>\1</em>", text) + + +def plain(text): + """Inline Markdown as plain text, for titles and the search index.""" + text = re.sub(r"`+([^`]+)`+", r"\1", text) + text = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", text) + return re.sub(r"\*+([^*]+)\*+", r"\1", text).strip() + + +# --- block Markdown ------------------------------------------------------------------------------------------- + +LIST_RE = re.compile(r"^( *)([-*]|\d+\.)(?: +(.*)|$)") +FENCE_RE = re.compile(r"^( *)```(\S*)\s*$") +HEADING_RE = re.compile(r"^(#{1,6}) +(.*?)\s*#*\s*$") + + +def indent_of(line): + return len(line) - len(line.lstrip(" ")) + + +def starts_block(line): + return bool(HEADING_RE.match(line) or FENCE_RE.match(line) or LIST_RE.match(line) or line.startswith("|") + or line.startswith(": ")) + + +class Renderer: + def __init__(self): + self.ids = {} + self.headings = [] + self.title = None + + def heading_id(self, text): + base = slug(text) + n = self.ids.get(base, 0) + self.ids[base] = n + 1 + return base if n == 0 else "%s-%d" % (base, n) + + def blocks(self, lines): + out, i = [], 0 + while i < len(lines): + line = lines[i] + if not line.strip(): + i += 1 + continue + m = FENCE_RE.match(line) + if m: + pad = len(m.group(1)) + body, i = [], i + 1 + while i < len(lines) and not re.match(r"^ *```\s*$", lines[i]): + body.append(lines[i][pad:] if lines[i][:pad].strip() == "" else lines[i]) + i += 1 + lang = m.group(2) + cls = ' class="language-%s"' % html.escape(lang) if lang else "" + out.append("<pre><code%s>%s</code></pre>" % (cls, html.escape("\n".join(body), quote=False))) + i += 1 + continue + m = HEADING_RE.match(line) + if m: + level, text = len(m.group(1)), m.group(2) + hid = self.heading_id(text) + if level == 1 and self.title is None: + self.title = plain(text) + self.headings.append({"level": level, "text": plain(text), "id": hid}) + anchor = '<a class="anchor" href="#%s" aria-label="Link to this section">#</a>' % hid if level > 1 else "" + out.append('<h%d id="%s">%s%s</h%d>' % (level, hid, inline(text), anchor, level)) + i += 1 + continue + if line.startswith("|"): + rows = [] + while i < len(lines) and lines[i].startswith("|"): + rows.append(lines[i]) + i += 1 + out.append(self.table(rows)) + continue + if i + 1 < len(lines) and lines[i + 1].startswith(": ") and not starts_block(line): + items = [] + while i + 1 < len(lines) and lines[i].strip() and lines[i + 1].startswith(": "): + term, i = lines[i], i + 1 + desc = [] + while i < len(lines) and lines[i].strip(): + desc.append(lines[i][4:] if lines[i].startswith(": ") else lines[i].strip()) + i += 1 + items.append("<dt>%s</dt><dd>%s</dd>" % (inline(term.strip()), inline("\n".join(desc)))) + while i < len(lines) and not lines[i].strip(): + i += 1 + out.append("<dl>%s</dl>" % "".join(items)) + continue + m = LIST_RE.match(line) + if m: + html_list, i = self.list(lines, i) + out.append(html_list) + continue + para = [] + while i < len(lines) and lines[i].strip() and not (para and starts_block(lines[i])): + para.append(lines[i].strip()) + i += 1 + out.append("<p>%s</p>" % inline("\n".join(para))) + return "\n".join(out) + + def list(self, lines, i): + first = LIST_RE.match(lines[i]) + base = len(first.group(1)) + ordered = first.group(2)[0].isdigit() + items = [] + while i < len(lines): + m = LIST_RE.match(lines[i]) + if not m or len(m.group(1)) != base or m.group(2)[0].isdigit() != ordered: + break + content_col = base + len(m.group(2)) + 1 + body = [m.group(3) or ""] if m.group(3) else [] + i += 1 + while i < len(lines): + ln = lines[i] + if not ln.strip(): + nxt = next((x for x in lines[i + 1:] if x.strip()), None) + if nxt is not None and indent_of(nxt) >= content_col - 1 and indent_of(nxt) > base: + body.append("") + i += 1 + continue + break + if indent_of(ln) > base: + body.append(ln[min(indent_of(ln), content_col):]) + i += 1 + continue + if body and not starts_block(ln): + body.append(ln.strip()) # a lazy continuation of the item's paragraph + i += 1 + continue + break + inner = self.blocks(body) + if inner.startswith("<p>") and inner.count("<p>") == 1 and inner.endswith("</p>"): + inner = inner[3:-4] + items.append("<li>%s</li>" % inner) + while i < len(lines) and not lines[i].strip(): + nxt = next((x for x in lines[i:] if x.strip()), None) + m2 = LIST_RE.match(nxt) if nxt else None + if m2 and len(m2.group(1)) == base: + i += 1 + else: + break + tag = "ol" if ordered else "ul" + start = int(first.group(2)[:-1]) if ordered else 1 + attr = ' start="%d"' % start if start != 1 else "" + return "<%s%s>%s</%s>" % (tag, attr, "".join(items), tag), i + + def table(self, rows): + def cells(row): + row = row.strip() + if row.startswith("|"): + row = row[1:] + if row.endswith("|"): + row = row[:-1] + out, cur, tick = [], "", False + for ch in row: + if ch == "`": + tick = not tick + if ch == "|" and not tick: + out.append(cur.strip()) + cur = "" + else: + cur += ch + out.append(cur.strip()) + return out + + head = cells(rows[0]) + body = [cells(r) for r in rows[2:]] if len(rows) > 1 and re.match(r"^\|[\s:|-]+\|?$", rows[1]) else \ + [cells(r) for r in rows[1:]] + thead = "<tr>%s</tr>" % "".join("<th>%s</th>" % inline(c) for c in head) + tbody = "".join("<tr>%s</tr>" % "".join("<td>%s</td>" % inline(c) for c in r) for r in body) + return '<div class="table-wrap"><table><thead>%s</thead><tbody>%s</tbody></table></div>' % (thead, tbody) + + +def render_markdown(text): + r = Renderer() + body = r.blocks(text.split("\n")) + return body, r + + +# --- pages ---------------------------------------------------------------------------------------------------- + +NAV = [ + ("Start", [("README.md", "Home"), ("docs/overview.md", "Overview"), ("docs/concepts.md", "Concepts"), + ("docs/walkthrough.md", "Walkthrough"), ("docs/examples.md", "Examples"), ("docs/faq.md", "FAQ"), + ("docs/glossary.md", "Glossary"), ("docs/rationale.md", "Rationale"), + ("docs/comparison.md", "Comparison")]), + ("Specification", None), + ("Reference", [("schemas/README.md", "Schemas"), ("registry/README.md", "Registry"), + ("vectors/README.md", "Test vectors"), ("fixtures/README.md", "Fixtures"), + ("sql/README.md", "SQL"), ("context/README.md", "JSON-LD context"), ("vocab", "Vocabulary"), + ("tools/README.md", "Tools")]), + ("Project", [("CHANGELOG.md", "Changelog"), ("CONTRIBUTING.md", "Contributing"), ("LICENSE.md", "Licenses")]), +] + + +def page_path(md_rel): + """Where the page for a Markdown file goes, relative to the site root.""" + head, base = os.path.split(md_rel) + if base == "README.md": + return os.path.join(head, "index.html") + return md_rel[:-3] + ".html" + + +def page_url(md_rel): + if md_rel == "vocab": + return "vocab/" + p = page_path(md_rel) + return p[:-len("index.html")] if p.endswith("index.html") else p + + +def rel(from_page, to_url): + """A relative link from the page at `from_page` to the site URL `to_url` (both relative to the root).""" + start = os.path.dirname(from_page) or "." + target = to_url or "./" + trailing = target.endswith("/") + r = os.path.relpath(target.rstrip("/") or ".", start) + if r == ".": + return "./" + return r + "/" if trailing else r + + +def spec_nav(): + out = [] + for f in sorted(os.listdir(os.path.join(ROOT, "spec"))): + if re.match(r"\d\d-.*\.md$", f): + with open(os.path.join(ROOT, "spec", f), encoding="utf-8") as fh: + m = re.search(r"^# (.*)$", fh.read(), re.M) + out.append(("spec/" + f, plain(m.group(1)) if m else f)) + return [("spec/README.md", "Contents")] + out + + +def nav_html(page, here_md): + """The sidebar for the page at `page`, marking `here_md` (a Markdown path, `vocab`, or None) as current.""" + current = page_url(here_md) if here_md else None + parts = [] + for group, entries in NAV: + entries = spec_nav() if entries is None else entries + links = [] + for md, label in entries: + url = page_url(md) + cur = ' aria-current="page"' if current == url else "" + links.append('<li><a href="%s"%s>%s</a></li>' % (html.escape(rel(page, url)), cur, html.escape(label))) + parts.append('<section><h2>%s</h2><ul>%s</ul></section>' % (html.escape(group), "".join(links))) + return "".join(parts) + + +CSS = """\ +:root { + --bg: #fbfaf8; --surface: #f2efea; --text: #1d1c1a; --muted: #5d5a54; --rule: #dedad3; + --accent: #1f5f8b; --accent-soft: #e3edf4; --code-bg: #efece6; --mark: #fff3c4; + --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace; +} +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) { + --bg: #161615; --surface: #1f1f1d; --text: #e9e6e0; --muted: #a6a29a; --rule: #34332f; + --accent: #7fb6dc; --accent-soft: #1d2c36; --code-bg: #24231f; --mark: #4a3f12; + } +} +:root[data-theme="dark"] { + --bg: #161615; --surface: #1f1f1d; --text: #e9e6e0; --muted: #a6a29a; --rule: #34332f; + --accent: #7fb6dc; --accent-soft: #1d2c36; --code-bg: #24231f; --mark: #4a3f12; +} +* { box-sizing: border-box; } +html { -webkit-text-size-adjust: 100%; } +body { margin: 0; background: var(--bg); color: var(--text); font: 16px/1.6 var(--sans); } +a { color: var(--accent); text-underline-offset: 2px; } +header.top { position: sticky; top: 0; z-index: 2; display: flex; gap: 1rem; align-items: center; + padding: .6rem 1rem; background: var(--bg); border-bottom: 1px solid var(--rule); } +header.top .brand { font-weight: 650; color: var(--text); text-decoration: none; letter-spacing: -.01em; } +header.top .version { color: var(--muted); font-size: .85rem; } +header.top .spacer { flex: 1; } +header.top input { width: min(18rem, 40vw); padding: .35rem .6rem; border: 1px solid var(--rule); border-radius: 6px; + background: var(--surface); color: var(--text); font: inherit; font-size: .9rem; } +.results { position: absolute; right: 1rem; top: 3rem; width: min(28rem, calc(100vw - 2rem)); max-height: 60vh; + overflow: auto; background: var(--bg); border: 1px solid var(--rule); border-radius: 8px; padding: .3rem 0; + box-shadow: 0 8px 24px rgba(0,0,0,.12); } +.results a { display: block; padding: .35rem .8rem; text-decoration: none; color: var(--text); } +.results a:hover, .results a:focus { background: var(--accent-soft); outline: none; } +.results small { display: block; color: var(--muted); } +.layout { display: grid; grid-template-columns: 16rem minmax(0, 1fr); max-width: 76rem; margin: 0 auto; } +nav.side { position: sticky; top: 3.2rem; align-self: start; max-height: calc(100vh - 3.2rem); overflow: auto; + padding: 1.2rem 1rem 2rem; font-size: .9rem; border-right: 1px solid var(--rule); } +nav.side h2 { font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); + margin: 1.2rem 0 .3rem; } +nav.side ul { list-style: none; margin: 0; padding: 0; } +nav.side a { display: block; padding: .15rem .4rem; border-radius: 4px; text-decoration: none; color: var(--text); } +nav.side a:hover { background: var(--surface); } +nav.side a[aria-current] { background: var(--accent-soft); color: var(--accent); font-weight: 600; } +main { padding: 1.5rem 2.5rem 4rem; min-width: 0; } +article { max-width: 48rem; } +h1, h2, h3, h4 { line-height: 1.25; letter-spacing: -.01em; } +h1 { font-size: 2rem; margin: .2rem 0 1rem; } +h2 { font-size: 1.4rem; margin: 2.2rem 0 .6rem; padding-top: .4rem; border-top: 1px solid var(--rule); } +h3 { font-size: 1.12rem; margin: 1.6rem 0 .4rem; } +h1, h2, h3, h4, h5, h6 { scroll-margin-top: 4rem; } +.anchor { margin-left: .4rem; color: var(--muted); text-decoration: none; opacity: 0; font-weight: 400; } +h2:hover .anchor, h3:hover .anchor, h4:hover .anchor, .anchor:focus { opacity: 1; } +:target { background: var(--mark); } +p, ul, ol, dl, pre, .table-wrap { margin: 0 0 1rem; } +li + li { margin-top: .25rem; } +code { font: .88em/1.4 var(--mono); background: var(--code-bg); padding: .1em .3em; border-radius: 4px; + overflow-wrap: anywhere; } +pre { background: var(--code-bg); padding: .8rem 1rem; border-radius: 6px; overflow-x: auto; } +pre code { background: none; padding: 0; font-size: .85rem; overflow-wrap: normal; } +.table-wrap { overflow-x: auto; } +table { border-collapse: collapse; font-size: .92rem; min-width: 60%; } +th, td { text-align: left; vertical-align: top; padding: .45rem .7rem; border-bottom: 1px solid var(--rule); } +th { background: var(--surface); font-weight: 600; } +dt { font-weight: 650; margin-top: 1rem; } +dd { margin: .2rem 0 0 1.2rem; } +.meta { margin-top: 3rem; padding-top: 1rem; border-top: 1px solid var(--rule); color: var(--muted); font-size: .85rem; } +.meta a { color: var(--muted); } +.listing td:last-child { text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; } +.crumbs { color: var(--muted); font-size: .9rem; margin-bottom: .5rem; } +details.menu { display: none; } +@media (max-width: 52rem) { + .layout { display: block; } + nav.side { display: none; } + details.menu { display: block; padding: .5rem 16px; border-bottom: 1px solid var(--rule); } + details.menu summary { cursor: pointer; font-weight: 600; } + details.menu nav.side { display: block; position: static; max-height: none; border: 0; padding: .5rem 0; } + main { padding: 1rem 16px 3rem; } + header.top { padding: .5rem 16px; } + header.top input { width: 9rem; } + h1 { font-size: 1.6rem; } +} +""" + +SEARCH_JS = """\ +(function () { + var input = document.getElementById("search"), box = document.getElementById("results"), index = null; + if (!input) return; + var root = document.documentElement.getAttribute("data-root") || ""; + function load(cb) { + if (index) return cb(); + fetch(root + "search.json").then(function (r) { return r.json(); }).then(function (j) { index = j; cb(); }) + .catch(function () { index = []; cb(); }); + } + function esc(s) { return s.replace(/[&<>"]/g, function (c) { return {"&": "&", "<": "<", ">": ">", '"': """}[c]; }); } + function show() { + var q = input.value.trim().toLowerCase(); + if (q.length < 2) { box.hidden = true; return; } + var hits = []; + index.forEach(function (p) { + if (p.title.toLowerCase().indexOf(q) >= 0) hits.push({url: p.url, text: p.title, page: ""}); + p.headings.forEach(function (h) { + if (h.text.toLowerCase().indexOf(q) >= 0) hits.push({url: p.url + "#" + h.id, text: h.text, page: p.title}); + }); + }); + hits = hits.slice(0, 25); + box.innerHTML = hits.length ? hits.map(function (h) { + return '<a href="' + root + esc(h.url) + '">' + esc(h.text) + (h.page ? "<small>" + esc(h.page) + "</small>" : "") + "</a>"; + }).join("") : '<a aria-disabled="true">No matching heading</a>'; + box.hidden = false; + } + input.addEventListener("input", function () { load(show); }); + input.addEventListener("keydown", function (e) { + if (e.key === "Escape") { box.hidden = true; input.blur(); } + if (e.key === "Enter") { var a = box.querySelector("a[href]"); if (a) location.href = a.href; } + }); + document.addEventListener("click", function (e) { if (!box.contains(e.target) && e.target !== input) box.hidden = true; }); + document.addEventListener("keydown", function (e) { + if (e.key === "/" && document.activeElement !== input) { e.preventDefault(); input.focus(); } + }); +})(); +""" + + +def layout(page, here_md, title, body, source=None, base_url=BASE_URL): + """A full page. `page` is the output path relative to the site root; `here_md` the Markdown it renders.""" + root = rel(page, "") + root = "" if root == "./" else root + ("" if root.endswith("/") else "/") + if page == "404.html": + root = "/" # served at whatever path was missing, so its links start from the site root + canonical = base_url.rstrip("/") + "/" + (page[:-len("index.html")] if page.endswith("index.html") else page) + nav = nav_html(page, here_md) + meta = "" + if source: + meta = ('<p class="meta">Source: <a href="%s/src/branch/main/%s">%s</a> · <a href="%s%s">raw</a></p>' + % (REPO, html.escape(source), html.escape(source), root, html.escape(source))) + return """<!doctype html> +<html lang="en" data-root="{root}"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<title>{title} + + + + + +

+{name}{version} + + + +
+ +
+ +
+{body} +{meta} +
+
+ + + +""".format(root=root, root_or_dot=root or "./", title=html.escape(title), canonical=html.escape(canonical), + name=NAME, version=html.escape(version()), nav=nav, body=body, meta=meta) + + +def size_text(n): + for unit in ("B", "KB", "MB"): + if n < 1024 or unit == "MB": + return ("%d %s" % (n, unit)) if unit == "B" else ("%.1f %s" % (n, unit)) + n /= 1024.0 + + +def listing(out, d, base_url): + """A page listing the files and folders of `d` (relative to the site root), for folders with no README.""" + full = os.path.join(out, d) + entries = sorted(os.listdir(full)) + rows = [] + if d: + rows.append('../') + for e in entries: + if e == "index.html": + continue + p = os.path.join(full, e) + if os.path.isdir(p): + rows.append('%s/' % (html.escape(e), html.escape(e))) + elif not (e.endswith(".html") and os.path.exists(os.path.join(full, e[:-5] + ".md"))): + rows.append('%s%s' + % (html.escape(e), html.escape(e), size_text(os.path.getsize(p)))) + crumbs = ['%s' % (rel(os.path.join(d, "index.html"), ""), NAME)] + parts = d.split("/") if d else [] + for i, part in enumerate(parts): + crumbs.append('%s' % (rel(os.path.join(d, "index.html"), "/".join(parts[:i + 1]) + "/"), + html.escape(part))) + body = ('

%s

%s/

' + '%s
NameSize
' + % (" / ".join(crumbs), html.escape(d or NAME), "".join(rows))) + with open(os.path.join(full, "index.html"), "w", encoding="utf-8") as f: + f.write(layout(os.path.join(d, "index.html"), None, (d or NAME) + "/ · " + NAME, body, base_url=base_url)) + + +def vocab_page(out, base_url): + """The page the context's term IRIs point at: one entry per IRI fragment of the `sct` namespace.""" + with open(os.path.join(ROOT, "context", "scienting-1.jsonld"), encoding="utf-8") as f: + ctx = json.load(f)["@context"] + prefix = ctx.get("sct", "") + rows = [] + for term, value in ctx.items(): + if term.startswith("@") or term in ("sct", "as"): + continue + iri = value if isinstance(value, str) else value.get("@id", "") + if not iri.startswith("sct:"): + continue + local = iri[4:] + notes = [] + if isinstance(value, dict): + if value.get("@type") == "@id": + notes.append("an IRI") + if value.get("@type") == "@json": + notes.append("a JSON literal, kept intact") + if value.get("@container"): + notes.append("a set") + rows.append('%s%s%s%s' + % (html.escape(local), html.escape(term), html.escape(prefix), html.escape(local), + html.escape(", ".join(notes)))) + body = ("

Vocabulary

The terms the JSON-LD context " + 'scienting-1.jsonld adds to the W3C Web ' + 'Annotation vocabulary. Each term's IRI is a fragment of this page; ' + 'the context's guide explains how layers use them.

' + '
%s' + "
TermIRIValue
" % "".join(rows)) + os.makedirs(os.path.join(out, "vocab"), exist_ok=True) + with open(os.path.join(out, "vocab", "index.html"), "w", encoding="utf-8") as f: + f.write(layout("vocab/index.html", "vocab", "Vocabulary · " + NAME, body, base_url=base_url)) + return {"title": "Vocabulary", "url": "vocab/", "headings": []} + + +def build(out, base_url=BASE_URL): + if os.path.exists(out): + shutil.rmtree(out) + os.makedirs(out) + mds = [] + for d, dirs, fs in os.walk(ROOT): + dirs[:] = sorted(x for x in dirs if x not in SKIP_DIRS and not (x.startswith(".") and x != ".well-known")) + reld = os.path.relpath(d, ROOT) + reld = "" if reld == "." else reld.replace(os.sep, "/") + if os.path.abspath(d) == os.path.abspath(out): + continue + for f in sorted(fs): + if f in SKIP_FILES or f.startswith("."): + continue + src = os.path.join(d, f) + if os.path.islink(src): + continue + dst = os.path.join(out, reld, f) + os.makedirs(os.path.dirname(dst), exist_ok=True) + shutil.copyfile(src, dst) + if f.endswith(".md"): + mds.append((reld + "/" + f) if reld else f) + index = [] + for md in mds: + with open(os.path.join(ROOT, md), encoding="utf-8") as f: + body, r = render_markdown(f.read()) + title = r.title or md + page = page_path(md) + full_title = (title + " · " + NAME) if md != "README.md" else NAME + " · " + title + with open(os.path.join(out, page), "w", encoding="utf-8") as f: + f.write(layout(page, md, full_title, body, source=md, base_url=base_url)) + index.append({"title": title, "url": page_url(md), + "headings": [{"text": h["text"], "id": h["id"]} for h in r.headings if h["level"] > 1]}) + index.append(vocab_page(out, base_url)) + for d, dirs, fs in os.walk(out): + reld = os.path.relpath(d, out) + reld = "" if reld == "." else reld.replace(os.sep, "/") + if "index.html" not in fs: + listing(out, reld, base_url) + with open(os.path.join(out, "404.html"), "w", encoding="utf-8") as f: + f.write(layout("404.html", None, "Not found · " + NAME, + '

Not found

No file of the specification has this address. ' + 'Start from the home page or search the headings above.

' + % html.escape(base_url.rstrip("/")), base_url=base_url)) + with open(os.path.join(out, "site.css"), "w", encoding="utf-8") as f: + f.write(CSS) + with open(os.path.join(out, "search.js"), "w", encoding="utf-8") as f: + f.write(SEARCH_JS) + with open(os.path.join(out, "search.json"), "w", encoding="utf-8") as f: + json.dump(sorted(index, key=lambda p: p["url"]), f, ensure_ascii=False, separators=(",", ":")) + f.write("\n") + return len(mds) + + +def main(): + ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + ap.add_argument("--out", default=os.path.join(ROOT, "_site"), help="the output folder (default _site/)") + ap.add_argument("--base-url", default=BASE_URL, help="the site's address, for canonical links (default %s)" % BASE_URL) + a = ap.parse_args() + out = os.path.abspath(a.out) + if out == ROOT or ROOT.startswith(out + os.sep): + ap.error("the output folder must not be the repository or contain it") + n = build(out, a.base_url) + print("Wrote %d pages and every file of the repository to %s" % (n, out)) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/stress.py b/tools/stress.py new file mode 100644 index 0000000..e46c40d --- /dev/null +++ b/tools/stress.py @@ -0,0 +1,732 @@ +#!/usr/bin/env python3 +"""Stress the reference implementation with random inputs. Exit status 0 means every property held. + +Non-normative tooling; it needs Python 3.14 and the packages pixi installs (`jsonschema`, `cryptography`). +Usage: python3 tools/stress.py [--seed N] [--rounds N] +The vectors pin values; this program checks the invariants the chapters state, over inputs drawn from a seeded +random generator, so a failure is reproducible from the seed it prints. Canonical JSON round-trips and sorts keys +by UTF-16 units; normalization is idempotent; notation folding never raises; random corrections keep the five +values equal to a full recomputation, never reuse an ID and apply deterministically; anchors made before those +corrections always resolve to one of the five outcomes; Merkle roots agree with a second implementation; +spot-check samples do not depend on input order; error bounds are the least six-decimal value with the stated tail; +differently stamped pages share a fingerprint; the zip reader and the package validator refuse or accept mutated +input without raising and never write outside their folders; rights combine the same in any order; and +spot-check chains hundreds deep settle without recursion. +""" + +import argparse +import copy +import json +import os +import random +import shutil +import sys +import tempfile +import time +import zipfile +from fractions import Fraction +from math import comb + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, ROOT) + +from tools.oracle import align as AL # noqa: E402 +from tools.oracle import anchors as AN # noqa: E402 +from tools.oracle import corrections as CO # noqa: E402 +from tools.oracle import crypto, fingerprint as FP, hashing, jcs, receipts as RC, rights as RI, targets as TG # noqa: E402 +from tools.oracle import keys as K, log as LG, mldsa, vrf # noqa: E402 +from tools.oracle import package as PK # noqa: E402 +from tools.oracle.model import LABELLED, LEAVES, Doc # noqa: E402 +from tools.oracle.notation import fold_math # noqa: E402 +from tools.oracle.text import NODE_ID_RE, RECORD_ID_RE, letter_first, norm, record_id, sha256_hex, is_ws # noqa: E402 +from tools.oracle.tree import Refusal, validate_structure # noqa: E402 +from tools.build import ROSTER_BY_ID, SCHEMAS, secret, sentence_doc, tiny_package # noqa: E402 +from tools.check import HALE, STORE, TINY_KEY, reference_values # noqa: E402 + +FAILS = [] +COUNTS = {} +RULES = {r["id"] for r in json.load(open(os.path.join(ROOT, "registry", "rules.json"), encoding="utf-8"))["rules"]} + + +def ok(section, cond, msg): + COUNTS[section] = COUNTS.get(section, 0) + 1 + if not cond and len(FAILS) < 200: + FAILS.append("%s: %s" % (section, msg)) + + +TEXT_POOL = list("abcdefghijklmnopqrstuvwxyzABCDEFXYZ0123456789 .,;:-()[]") + [ + "é", "Å", "fi", "µ", "−", "–", " ", "\t", "\n", "
", "€", + "\U0001d49c", "\U0001f600", "é", "H₂O", "10³", "cm⁻¹", " "] +KEY_POOL = list("abcxyz") + ["€", "\U0001f600", "fi", "A", "é", "", "a b", "\u0001"] + + +def rand_text(rng, lo=0, hi=12, pool=TEXT_POOL): + return "".join(rng.choice(pool) for _ in range(rng.randint(lo, hi))) + + +def rand_json(rng, depth=0): + r = rng.random() + if depth > 3 or r < 0.4: + choice = rng.randint(0, 6) + if choice == 0: + return None + if choice == 1: + return rng.random() < 0.5 + if choice == 2: + return rng.randint(-2**53, 2**53) + if choice == 3: + return rng.uniform(-1, 1) * 10.0 ** rng.randint(-12, 24) + if choice == 4: + return rng.choice([0, -0.0, 1e21, 1e-7, 0.000001, 123456789.125, 5e-324, 1.7976931348623157e308]) + return rand_text(rng) + if r < 0.7: + return [rand_json(rng, depth + 1) for _ in range(rng.randint(0, 4))] + return {rand_text(rng, 0, 3, KEY_POOL): rand_json(rng, depth + 1) for _ in range(rng.randint(0, 4))} + + +def _as_doubles(text): + """Parse JSON as an ECMAScript engine does, which is how canonical JSON is read (vectors/README.md).""" + return json.loads(text, parse_int=lambda x: int(x) if abs(int(x)) <= 2**53 else float(x)) + + +def stress_canonical_json(rng, rounds): + for _ in range(rounds): + v = rand_json(rng) + try: + s = jcs.dumps(v) + except ValueError as e: + ok("canonical-json", False, "dumps refused a plain value: %r (%s)" % (v, e)) + continue + ok("canonical-json", jcs.dumpb(v) == s.encode("utf-8"), "dumpb is dumps encoded") + back = _as_doubles(s) + ok("canonical-json", back == v, "round trip changed the value: %r" % (v,)) + ok("canonical-json", jcs.dumps(back) == s, "canonical form is not idempotent for %r" % (v,)) + pairs = _as_doubles(s) if not s.startswith(("{", "[")) else json.loads(s, object_pairs_hook=lambda kv: kv) + + def ordered(x): + if isinstance(x, list) and x and isinstance(x[0], tuple): + keys = [k for k, _ in x] + return keys == sorted(keys, key=lambda k: k.encode("utf-16-be")) and all(ordered(v) for _, v in x) + if isinstance(x, list): + return all(ordered(y) for y in x) + return True + ok("canonical-json", ordered(pairs), "object members are not sorted by UTF-16 code units in %s" % s[:80]) + + +def stress_normalization(rng, rounds): + for _ in range(rounds): + s = rand_text(rng, 0, 30) + n = norm(s) + ok("normalize", norm(n) == n, "normalization is not idempotent for %r" % s) + ok("normalize", not n or (not is_ws(n[0]) and not is_ws(n[-1])), "normalized text keeps edge whitespace") + ok("normalize", " " not in n and all(ch == " " or not is_ws(ch) for ch in n), + "normalized text keeps a whitespace run or a non-space whitespace: %r" % n) + + +TEX_TOKENS = list("xyzKrHO0123456789+-=()'") + ["_", "^", "{", "}", "\\alpha", "\\mathrm{H}", "\\frac{a}{b}", " ", + "\\,", "\\cdot", "H_2O", "^{14}", "{}", "\\left(", "\\right)", "\\\\", + "µ", "−", "''", "_{", "^{"] +TYPST_TOKENS = list("xyzKr0123456789+-=()'") + ["_", "^", "(", ")", "alpha", "upright(H)", "\"cm\"", " ", "dot", + "plus.minus", "<=", "/", "epsilon.alt", "_(", "^(", "\"a\\b\""] + + +def stress_notation(rng, rounds): + for _ in range(rounds): + for notation, pool in (("tex", TEX_TOKENS), ("typst", TYPST_TOKENS)): + s = "".join(rng.choice(pool) for _ in range(rng.randint(0, 8))) + try: + a = fold_math(notation, s) + b = fold_math(notation, s) + except Exception as e: # noqa: BLE001 + ok("notation", False, "fold_math raised %r on %s %r" % (e, notation, s)) + continue + ok("notation", a == b and (a is None or isinstance(a, str)), "fold_math is not deterministic on %r" % s) + ok("notation", a is None or not any(is_ws(ch) for ch in a), "a canonical form holds whitespace: %r" % a) + ok("notation", a is None or "$" not in a, "a canonical form holds a dollar sign: %r" % a) + + +def _leaf_ids(doc, kinds): + return [nid for nid in doc.preorder() if doc.nodes[nid]["kind"] in kinds] + + +def random_correction(rng, st, doc): + """One random proposal against `st`, or None.""" + sentences = _leaf_ids(doc, {"sentence"}) + cells = _leaf_ids(doc, {"cell"}) + op = rng.choice(["replace", "replace", "split", "merge", "move", "relabel", "set", "delete", "reclassify", + "insert-text", "insert-node"]) + evidence = [{"kind": "crop", "sha256": "0" * 64}] if rng.random() < 0.8 else [{"kind": "person", "by": "ana"}] + c = {"op": op.split("-")[0], "evidence": evidence} + if op == "replace" and (sentences or cells): + nid = rng.choice(sentences + cells) + text = hashing.plain(doc, nid) + if not text: + return None + i = rng.randrange(len(text)) + j = min(len(text), i + rng.randint(1, 6)) + c.update(target=nid, find=text[i:j], replace=rand_text(rng, 0, 8)) + elif op == "split" and sentences: + nid = rng.choice(sentences) + c.update(target=nid, offset=rng.randint(0, max(1, len(hashing.plain(doc, nid))))) + elif op == "merge" and len(sentences) > 1: + nid = rng.choice(sentences) + sibs = doc.kids(doc.nodes[nid]["parent"]) + k = sibs.index(nid) + other = sibs[k + 1] if k + 1 < len(sibs) else rng.choice(sentences) + c.update(target=nid, **{"with": other}, joiner=rng.choice([" ", ""])) + elif op == "move" and sentences: + paragraphs = _leaf_ids(doc, {"paragraph"}) + if not paragraphs: + return None + c.update(target=rng.choice(sentences), parent=rng.choice(paragraphs), place_after=None) + elif op == "relabel": + labelled = [nid for nid in doc.preorder() if doc.nodes[nid]["kind"] in LABELLED] + if not labelled: + return None + c.update(target=rng.choice(labelled), label=rng.choice([None, "2", "Table 7", "a", rand_text(rng, 1, 5)])) + elif op == "set" and cells: + c.update(target=rng.choice(cells), attr=rng.choice(["colspan", "rowspan", "role", "column", "level"]), + value=rng.choice([1, 2, 3, "2", -1, "data", "row-header", "boss", None])) + elif op == "delete" and len(doc.order) > 8: + c.update(target=rng.choice(doc.order[1:])) + elif op == "reclassify": + c.update(target=rng.choice(doc.order), kind=rng.choice(["footnote", "quote", "paragraph", "caption", "section"])) + elif op == "insert-text" and sentences: + nid = rng.choice(sentences) + c.update(target=nid, run=rng.randint(0, len(doc.nodes[nid]["content"])), offset=rng.randint(0, 20), + text=rand_text(rng, 1, 6)) + elif op == "insert-node": + paragraphs = _leaf_ids(doc, {"paragraph"}) + if not paragraphs: + return None + parent = rng.choice(paragraphs) + kids = doc.kids(parent) + node = {"kind": "sentence", "content": [{"kind": "text", "text": rand_text(rng, 1, 20) or "x"}]} + if rng.random() < 0.2: + node["foo"] = 1 + c.update(parent=parent, place_after=rng.choice(kids + [None]), node=node) + else: + return None + return c + + +def stress_corrections(rng, rounds): + """A random walk of corrections from the tiny document; returns the states it passed through.""" + tiny = tiny_package(None, receipts=False) + st = tiny["final"] + base = {"author": {"key": "ana"}, "reason": "Stress.", "at": "2026-10-11T12:00:00Z"} + seen = {n["id"] for n in st.nodes} + history, accepted = [st], 0 + for _ in range(rounds): + doc = st.doc() + c = random_correction(rng, st, doc) + if c is None: + continue + c = dict(base, **c) + try: + st1, rec = CO.apply(st, copy.deepcopy(c), store=SCHEMAS) + except Refusal as e: + ok("corrections", e.rule in RULES, "a refusal names the unregistered rule %s" % e.rule) + continue + except Exception as e: # noqa: BLE001 + ok("corrections", False, "apply raised %r on %s" % (e, json.dumps(c)[:160])) + continue + accepted += 1 + try: + validate_structure(st1.doc()) + ok("corrections", st1.index().values == reference_values(st1.doc()), + "incremental values differ from the full computation after %s" % c["op"]) + except Refusal as e: + ok("corrections", False, "an accepted correction left the tree invalid: %s" % e.rule) + new_ids = {n["id"] for n in st1.nodes} - {n["id"] for n in st.nodes} + ok("corrections", not (new_ids & seen), "an ID was reused: %s" % sorted(new_ids & seen)) + seen |= new_ids + table = {e["id"] for e in st1.ids} + ok("corrections", set(rec.get("retired", [])) <= table, "a retired ID is not in the ID table") + ok("corrections", st1.ids == sorted(st1.ids, key=CO.id_order), "ids are not in the order of spec/04 §4.4") + ok("corrections", rec["id"] == record_id(sha256_hex(jcs.dumpb({k: v for k, v in rec.items() if k != "id"}))), + "the record's id does not derive from its content") + ok("corrections", rec["index"] == st.rev + 1 == st1.rev, "the record's index is not the next revision") + st2, rec2 = CO.apply(st, copy.deepcopy(c), store=SCHEMAS) + ok("corrections", rec2 == rec and st2.nodes == st1.nodes and st2.ids == st1.ids, "apply is not deterministic") + try: + _, rec3 = CO.gate(st, copy.deepcopy(c), SCHEMAS) + ok("corrections", rec3 == rec, "the gate records something else than apply") + except Refusal as e: + ok("corrections", e.rule == "correction.schema", "the gate refused an applied correction with %s" % e.rule) + st = st1 + history.append(st) + ok("corrections", accepted >= rounds // 10, "too few random corrections were accepted: %d of %d" % (accepted, rounds)) + return history + + +def stress_anchors(rng, history, rounds): + st0, final = history[0], history[-1] + doc0, vals0 = st0.doc(), hashing.compute(st0.doc()) + outcomes = {"current", "changed-below", "moved", "reattached", "stale"} + seen_outcomes = set() + anchors = [] + for nid in doc0.preorder(): + anchors.append(AN.make_anchor(doc0, vals0, nid, 0, store="smithlab")) + if doc0.nodes[nid]["kind"] in LEAVES: + t = hashing.plain(doc0, nid) + if len(t) > 2: + i = rng.randrange(len(t) - 1) + j = rng.randint(i + 1, len(t)) + anchors.append(AN.make_anchor(doc0, vals0, nid, 0, span=[i, j], store="smithlab")) + for _ in range(rounds // 4): + a = copy.deepcopy(rng.choice(anchors)) + a["node"] = letter_first(os.urandom(32), 7) if rng.random() < 0.5 else a["node"] + a.pop("kind", None) + anchors.append(a) + for state in (final, history[len(history) // 2], history[min(1, len(history) - 1)]): + values = hashing.compute(state.doc()) + for a in anchors: + try: + r = AN.resolve(state, a) + except Exception as e: # noqa: BLE001 + ok("anchors", False, "resolve raised %r on %s" % (e, json.dumps(a)[:120])) + continue + ok("anchors", r["result"] in outcomes, "unknown outcome %s" % r.get("result")) + seen_outcomes.add(r["result"]) + if r["result"] != "stale" or r.get("node"): + ok("anchors", r.get("node") in state.doc().nodes, "a non-stale result names no live node") + if r["result"] == "current": + ok("anchors", values[r["node"]]["node_hash"] == a["node_hash"], "current with another node_hash") + if "span" in r: + t = hashing.plain(state.doc(), r["node"]) + ok("anchors", 0 <= r["span"][0] <= r["span"][1] <= len(t), "a span outside the node's text") + ok("anchors", {"current", "stale"} <= seen_outcomes, "the random walk produced only %s" % sorted(seen_outcomes)) + + +def _merkle_reference(items): + leaves = [sha256_hex(b"\x00" + jcs.dumpb(x)) for x in items] + + def mth(ls): + if len(ls) == 1: + return ls[0] + k = 1 + while 2 * k < len(ls): + k *= 2 + return sha256_hex(b"\x01" + bytes.fromhex(mth(ls[:k])) + bytes.fromhex(mth(ls[k:]))) + return mth(leaves) + + +def stress_merkle(rng, rounds): + """Receipt items are lists, `["node", id, hash]` or `[kind, record id, hash]` (spec/08 §8.5).""" + for _ in range(rounds): + n = rng.randint(1, 40) + items = [[rng.choice(["node", "annotation", "digitization", "checklist"]), letter_first(os.urandom(32), 7), + sha256_hex(os.urandom(8))] for _ in range(n)] + if rng.random() < 0.3: + items.append([rand_text(rng), [rand_text(rng)], rng.randint(0, 2**53)]) + ok("merkle", crypto.merkle_root(items) == _merkle_reference(items), "Merkle roots differ for %d items" % len(items)) + + +def stress_spotcheck(rng, rounds): + for _ in range(rounds): + n = rng.randint(1, 60) + ids = sorted({letter_first(os.urandom(32), 7) for _ in range(n)}) + receipt = {"format": "scienting-receipt/1", "nodes": [[i, sha256_hex(i)] for i in ids]} + seed = RC.make_seed(receipt, os.urandom(32)) + rate, minimum = rng.choice(["0.05", "0.1", "0.5", "1"]), rng.randint(1, 15) + sample = RC.sample(receipt, seed, rate, minimum) + try: + RC.sample(receipt, os.urandom(64), rate, minimum) + ok("spot-check", False, "random bytes were accepted as a seed") + except ValueError: + pass + size = RC.sample_size(len(ids), rate, minimum) + ok("spot-check", len(sample) == size == min(len(ids), max(minimum, -(-Fraction(rate) * len(ids) // 1))), + "sample size %d is not the rule's for n=%d" % (len(sample), len(ids))) + ok("spot-check", sample == sorted(sample) and set(sample) <= set(ids), "sample is not sorted or not from the receipt") + shuffled = {"nodes": rng.sample(receipt["nodes"], len(receipt["nodes"]))} + ok("spot-check", RC.sample(shuffled, seed, rate, minimum) == sample, "the sample depends on input order") + + +def stress_bounds(rng, rounds): + alpha = Fraction(5, 100) + for _ in range(rounds // 4): + n = rng.randint(1, 120) + k = rng.randint(0, n) + b = RC.bound_string(k, n) + ok("bounds", len(b.split(".")[1]) == 6, "bound has not six decimals: %s" % b) + if k >= n: + ok("bounds", b == "1.000000", "k = n must give 1") + continue + p = Fraction(b) + + def tail(q): + return sum(comb(n, i) * q**i * (1 - q)**(n - i) for i in range(k + 1)) + ok("bounds", tail(p) <= alpha, "the tail at the bound is above alpha for k=%d n=%d" % (k, n)) + if p > 0: + ok("bounds", tail(p - Fraction(1, 10**6)) > alpha, "the bound is not the least six-decimal value for k=%d n=%d" % (k, n)) + if k + 1 < n: + ok("bounds", Fraction(RC.bound_string(k + 1, n)) >= p, "the bound is not monotone in k") + + +def stress_fingerprints(rng, rounds): + rules = json.load(open(os.path.join(ROOT, "registry", "stamps", "scienting-stamps-1.json"), encoding="utf-8"))["rules"] + for _ in range(rounds): + lines = [{"text": rand_text(rng, 1, 40)} for _ in range(rng.randint(1, 8))] + page = {"size": [612.0, 792.0], "lines": lines, "images": [sha256_hex(rand_text(rng)) for _ in range(rng.randint(0, 2))]} + stamped = copy.deepcopy(page) + stamped["lines"].insert(rng.randint(0, len(lines)), + {"text": "Downloaded via EXAMPLE UNIV on %s" % rand_text(rng, 1, 10, list("abcXYZ0123456789-:"))}) + fp, removed = FP.fingerprint(page, rules) + fp2, removed2 = FP.fingerprint(stamped, rules) + ok("fingerprints", fp == fp2 and len(removed2) == len(removed) + 1, "a stamped download has another fingerprint") + digit_lines = [i for i, l in enumerate(lines) if any(ch in "0123456789" for ch in l["text"])] + if digit_lines: + changed = copy.deepcopy(page) + i = rng.choice(digit_lines) + t = changed["lines"][i]["text"] + j = next(j for j, ch in enumerate(t) if ch in "0123456789") + changed["lines"][i]["text"] = t[:j] + str((int(t[j]) + 1) % 10) + t[j + 1:] + ok("fingerprints", FP.fingerprint(changed, rules)[0] != fp, "a changed digit kept the fingerprint") + spaced = copy.deepcopy(page) + spaced["lines"] = [{"text": " ".join(l["text"])} for l in spaced["lines"]] + ok("fingerprints", FP.fingerprint(spaced, rules)[0] == fp, "inserted spaces changed the fingerprint") + + +def stress_zip(rng, rounds): + src = os.path.join(ROOT, "fixtures", "packages", TINY_KEY + PK.ZIP_EXTENSION) + with open(src, "rb") as f: + good = f.read() + accepted = 0 + with tempfile.TemporaryDirectory() as tmp: + for i in range(rounds): + data = bytearray(good) + mode = rng.random() + if mode < 0.6: + for _ in range(rng.randint(1, 3)): + data[rng.randrange(len(data))] = rng.randrange(256) + elif mode < 0.8: + data = data[:rng.randrange(len(data))] + else: + data = data[:rng.randrange(len(data))] + os.urandom(rng.randint(1, 64)) + data[rng.randrange(len(data)):] + path = os.path.join(tmp, "z%d.zip" % i) + with open(path, "wb") as f: + f.write(data) + try: + rep = PK.validate_zip(path, STORE) + except Exception as e: # noqa: BLE001 + ok("zip", False, "validate_zip raised %r on mutation %d" % (e, i)) + continue + accepted += bool(rep) + dest = os.path.join(tmp, "d%d" % i) + try: + PK.read_zip(path, dest) + except Refusal as e: + ok("zip", e.rule in RULES, "read_zip names the unregistered rule %s" % e.rule) + except Exception as e: # noqa: BLE001 + ok("zip", False, "read_zip raised %r on mutation %d" % (e, i)) + stray = [f for f in os.listdir(tmp) if not (f.startswith("z") and f.endswith(".zip")) and not f.startswith("d")] + ok("zip", not stray, "the zip reader wrote outside its folder: %s" % stray) + ok("zip", accepted <= rounds // 20 + 1, "%d of %d mutated archives were accepted" % (accepted, rounds)) + + +def stress_packages(rng, rounds): + src = os.path.join(ROOT, "fixtures", "packages", TINY_KEY) + files = sorted(os.path.relpath(os.path.join(d, f), src) for d, _, fs in os.walk(src) for f in fs) + with tempfile.TemporaryDirectory() as tmp: + for i in range(rounds): + pkg = os.path.join(tmp, "p%d" % i) + shutil.copytree(src, pkg) + mode = rng.choice(["flip", "flip", "truncate", "delete", "add", "rename-case", "symlink"]) + target = rng.choice(files) + full = os.path.join(pkg, target) + if mode == "flip": + data = bytearray(open(full, "rb").read()) + if data: + k = rng.randrange(len(data)) + data[k] = (data[k] + rng.randrange(1, 256)) % 256 + open(full, "wb").write(data) + elif mode == "truncate": + data = open(full, "rb").read() + open(full, "wb").write(data[:rng.randrange(len(data) + 1)]) + elif mode == "delete": + os.remove(full) + elif mode == "add": + open(os.path.join(pkg, rand_text(rng, 1, 8, list("abcxyz")) + ".txt"), "wb").write(b"stray\n") + elif mode == "rename-case": + if target.lower() == target.upper(): + continue + os.rename(full, os.path.join(pkg, target.upper())) + else: + os.remove(full) + os.symlink(os.path.join(src, target), full) + try: + rep = PK.validate(pkg, STORE) + except Exception as e: # noqa: BLE001 + ok("packages", False, "validate raised %r after %s of %s" % (e, mode, target)) + continue + ok("packages", not rep, "a package mutated by %s of %s validated" % (mode, target)) + ok("packages", all(e["rule"] in RULES for e in rep.errors), "an unregistered rule was reported") + shutil.rmtree(pkg) + + +def stress_rights(rng, rounds): + tri = [True, False, "unknown"] + keys = list(RI.USES) + ["ai/" + p for p in RI.AI_PAIRS] + for _ in range(rounds): + flats = [{k: rng.choice(tri) for k in keys} for _ in range(rng.randint(1, 4))] + combined = RI.combine(flats) + shuffled = RI.combine(rng.sample(flats, len(flats))) + ok("rights", combined == shuffled, "combining depends on order") + for k in keys: + vals = [f[k] for f in flats] + want = False if False in vals else ("unknown" if "unknown" in vals else True) + ok("rights", combined[k] == want, "combining %s gave %r for %r" % (k, combined[k], vals)) + + +def _align_items(rng, prefix, texts): + items = [] + for i, t in enumerate(texts): + runs = [{"kind": "text", "text": t}] + doc, s = sentence_doc(runs) + strict, cx = hashing.strict(doc, s) + items.append({"id": "%s%d" % (prefix, i), "container": "p%d" % (i // 3), "context": "paragraph", "runs": runs, + "strict": strict, "lossy": hashing.lossy_from_strict(strict), "complex": cx}) + return items + + +def stress_alignment(rng, rounds): + for _ in range(rounds // 4): + texts = [rand_text(rng, 5, 60) or "x" for _ in range(rng.randint(1, 12))] + a = _align_items(rng, "a", texts) + try: + same = AL.align(a, _align_items(rng, "b", texts)) + b_texts = [t for t in texts if rng.random() > 0.3] + [rand_text(rng, 5, 30)] + diff = AL.align(a, _align_items(rng, "b", b_texts)) + ok("alignment", AL.align(a, _align_items(rng, "b", b_texts)) == diff, "alignment is not deterministic") + except Exception as e: # noqa: BLE001 + ok("alignment", False, "align raised %r" % (e,)) + continue + ok("alignment", len(same["pairs"]) == len(a) and all(p["agree"] for p in same["pairs"]) + and not [s for s in same["suspects"] if s["kind"] not in ("structure", "join")], + "aligning two equal readings left disagreements or unpaired sentences: %s" % same["suspects"][:3]) + ids_a = {x["id"] for x in a} + ok("alignment", all(p["a"] in ids_a for p in diff["pairs"]), "a pair names an unknown sentence") + paired = {p["a"] for p in diff["pairs"]} + dropped = {s["a"] for s in diff["suspects"] if s["kind"] == "dropped"} + ok("alignment", paired | dropped == ids_a and not (paired & dropped), + "every sentence of a reading is paired or dropped, not both or neither") + + +def stress_addresses(rng, rounds): + for _ in range(rounds): + store = rng.choice([None, "smithlab", "a1", "x.y-z"]) + key = rng.choice([HALE, "k-0000", "a1-aaaa.si", "x-k3f9qd.v2"]) + node = letter_first(os.urandom(32), 7) + pin = sha256_hex(rand_text(rng))[:6] if rng.random() < 0.5 else None + span = sorted([rng.randint(0, 50), rng.randint(0, 50)]) if rng.random() < 0.5 else None + s = AN.format_address(store, key, node, pin, span) + parsed = AN.parse_address(s) + ok("addresses", parsed and AN.format_address(parsed["store"], parsed["key"], parsed["node"], parsed["pin"], + parsed["span"]) == s, "address does not round trip: %s" % s) + junk = rand_text(rng, 0, 20) + try: + AN.parse_address(junk) + except Exception as e: # noqa: BLE001 + ok("addresses", False, "parse_address raised %r on %r" % (e, junk)) + for _ in range(rounds): + d = os.urandom(32) + ok("ids", NODE_ID_RE.match(letter_first(d, 7)) and RECORD_ID_RE.match(record_id(d.hex())), "ID form") + + +def stress_targets(rng, rounds): + st = PK.read_state(os.path.join(ROOT, "fixtures", "packages", HALE)) + doc = st.doc() + for _ in range(rounds // 4): + anchored = rng.sample(doc.order, rng.randint(0, 6)) + sets = {} + for rule in TG.DIGIT_RULES: + got = TG.target_set(doc, anchored, rule) + ids = [n for n, _ in got] + pos = {nid: i for i, nid in enumerate(doc.order)} + ok("targets", ids == sorted(ids, key=pos.get) and len(set(ids)) == len(ids), "targets are not in document order") + ok("targets", all(doc.nodes[n]["kind"] in LEAVES for n in ids), "a target is not a leaf") + sets[rule] = set(ids) + ok("targets", sets["none"] <= sets["anchored-sections"] <= sets["all"], "the digit rules do not nest") + try: + TG.target_set(doc, anchored + ["zzzzzzz"], "all") + ok("targets", False, "an unknown anchored node was accepted") + except ValueError: + ok("targets", True, "") + + +def stress_receipt_chains(rng, rounds): + """Chains of spot-checks hundreds deep settle without recursion, and alternate as spec/08 §8.6 implies.""" + depth = max(50, rounds) + ids = sorted({letter_first(os.urandom(32), 7) for _ in range(20)}) + rec = RC.seal({"format": "scienting-receipt/1", "doc": HALE, "rev": 0, "level": "F3", "scope": "all", + "nodes": [[i, sha256_hex(i)] for i in ids], "evidence": [], "by": "ana", + "at": "2026-10-11T12:00:00Z"}, secret("ana"), "ana") + records = [rec] + for i in range(depth): + orig = records[-1] + seed = RC.make_seed(orig, secret("ben-spot")) + sample = RC.sample(orig, seed) + hashes = dict(orig["nodes"]) + q = RC.seal({"format": "scienting-receipt/1", "doc": HALE, "rev": 0, "level": "F3", + "scope": "qa:" + orig["id"], "nodes": [[n, hashes[n]] for n in sample], "evidence": [], + "by": "ben", "at": "2026-10-11T12:%02d:%02dZ" % (i // 60 % 60, i % 60), + "qa": {"of": orig["id"], "key": "ben-spot", "seed": __import__("base64").b64encode(seed).decode(), + "rate": "0.05", "minimum": 10, "sample": sample, "errors": [{"node": sample[0]}]}}, + secret("ben"), "ben") + records.append(q) + t0 = time.time() + try: + status = RC.statuses(records, ROSTER_BY_ID) + except RecursionError: + ok("receipts", False, "a chain of %d spot-checks overflowed the stack" % depth) + return + ok("receipts", time.time() - t0 < 30, "statuses of a %d-deep chain took too long" % depth) + # The last spot-check nobody checks is valid; each receipt it checks is suspended; and so on, alternating. + want = "valid" + for r in reversed(records): + ok("receipts", status[r["id"]] == want, "receipt at depth %d is %s, not %s" % (records.index(r), status[r["id"]], want)) + want = "suspended" if want == "valid" else "valid" + + +def stress_keys(rng, rounds): + """Keys (spec/02 §2.4): the pattern always holds, the suffix is a prefix of longer ones, lengthening settles a + collision without touching the first key, and a key's hash part depends on the identity alone.""" + words = ["Attention", "On", "the", "Origin", "of", "Species", "H\u2082O", "3D", "Self-consistent", "\u00c9tude", "\u5f20", "don't", "a"] + for _ in range(rounds): + meta = {"title": " ".join(rng.choice(words) for _ in range(rng.randint(0, 6))), + "author": [{"family": rng.choice(["M\u00fcller", "O'Brien", "\u5f20\u4f1f", "", "de la Cruz", "Smith Jr."])}] if rng.random() < 0.8 else [], + "issued": {"date-parts": [[rng.choice([2017, 1859, 99, 20261, None])]]} if rng.random() < 0.8 else {}} + same_as = [rng.choice(["doi:10.1/X.Y", "doi:10.1/x.y", "arxiv:1706.03762", "url:https://e.org/p", "openalex:W1"])] if rng.random() < 0.6 else [] + key = K.work_key(same_as, meta) + ok("keys", K.WORK_KEY_RE.match(key) and K.DOCUMENT_KEY_RE.match(key), "a minted key breaks the pattern: %r" % key) + ident = K.identity(same_as, meta) + ok("keys", K.suffix(ident, 8).startswith(K.suffix(ident)), "a longer suffix does not extend the shorter") + longer = K.unique_work_key(same_as, meta, {key}) + ok("keys", longer != key and longer.startswith(key) and len(longer) == len(key) + 2, "lengthening does not extend the key") + if same_as and same_as[0].lower().startswith("doi:"): + other = dict(meta, title="Another title entirely") + ok("keys", K.suffix_of(K.work_key(same_as, other)) == K.suffix_of(key), "the hash part depends on more than the identity") + for v in ({"type": "version-of-record"}, {"type": "supplement"}, {"type": "preprint", "seq": rng.randint(1, 9)}, {"type": "erratum"}): + dk = K.document_key(key, v) + ok("keys", K.DOCUMENT_KEY_RE.match(dk) and K.split_key(dk)[0] == key, "a document key does not split back") + + +def stress_vrf(rng, rounds): + """The VRF proves and verifies for random keys and inputs, and a single flipped byte never verifies.""" + for _ in range(max(5, rounds // 20)): + sk = os.urandom(32) + pk = vrf.public_key(sk) + alpha = os.urandom(rng.randint(0, 40)) + pi = vrf.prove(sk, alpha) + beta = vrf.verify(pk, alpha, pi) + ok("vrf", beta is not None and beta == vrf.proof_to_hash(pi) and len(pi) == 80 and len(beta) == 64, "a proof does not verify") + ok("vrf", vrf.prove(sk, alpha) == pi, "proving is not deterministic") + bad = bytearray(pi) + bad[rng.randrange(80)] ^= 1 << rng.randrange(8) + ok("vrf", vrf.verify(pk, alpha, bytes(bad)) is None, "a tampered proof verifies") + ok("vrf", vrf.verify(pk, alpha + b"x", pi) is None and vrf.verify(vrf.public_key(os.urandom(32)), alpha, pi) is None, + "a proof verifies for another input or key") + ok("vrf", vrf.verify(pk, alpha, os.urandom(80)) is None and vrf.verify(os.urandom(32), alpha, pi) is None, "garbage verifies") + + +def stress_proofs(rng, rounds): + """RFC 9162 inclusion and consistency proofs verify for every index and prefix of random trees, and fail for a + wrong index, root or size.""" + for _ in range(rounds // 4): + n = rng.randint(1, 40) + items = [["node", letter_first(os.urandom(32), 7), sha256_hex(os.urandom(4))] for _ in range(n)] + root = crypto.history_root(items) + for i in range(n): + path = crypto.inclusion_path(items, i) + leaf = crypto.leaf_hash(items[i]) + ok("proofs", crypto.verify_inclusion(root, leaf, i, n, path), "inclusion fails for %d of %d" % (i, n)) + ok("proofs", n == 1 or not crypto.verify_inclusion(root, leaf, (i + 1) % n, n, path), "inclusion passes for another index") + ok("proofs", not crypto.verify_inclusion(sha256_hex(b"x"), leaf, i, n, path), "inclusion passes for another root") + # A wrong size is not always detectable from a path: RFC 9162 commits to the content through the + # root, and two sizes with one tree shape verify alike. The root is what a verifier must trust. + for m in range(n + 1): + proof = crypto.consistency_proof(items, m) + ok("proofs", crypto.verify_consistency(crypto.history_root(items[:m]), root, m, n, proof), "consistency fails %d to %d" % (m, n)) + if 0 < m < n: + ok("proofs", not crypto.verify_consistency(sha256_hex(b"x"), root, m, n, proof) + and not crypto.verify_consistency(crypto.history_root(items[:m]), sha256_hex(b"y"), m, n, proof), + "a consistency proof passes with a wrong root") + ok("proofs", not crypto.verify_consistency(crypto.history_root(items[:1]), root, 1, n, ["zz"]), "garbage path verifies") + + +def stress_checkpoints(rng, rounds): + """Checkpoint notes parse back to what was signed and reject edits anywhere.""" + for _ in range(rounds // 10): + entries = [[rng.choice(["receipt", "revocation"]), letter_first(os.urandom(32), 13), sha256_hex(os.urandom(4))] + for _ in range(rng.randint(0, 20))] + note = LG.sign_checkpoint("scient.ing/log/t", entries, [("ana", secret("ana")), ("ben", secret("ben"))]) + parsed, verified = LG.verify_checkpoint(note, ROSTER_BY_ID) + ok("checkpoints", parsed and parsed["size"] == len(entries) and parsed["root"] == LG.root(entries) and verified == ["ana", "ben"], + "a checkpoint does not verify") + k = rng.randrange(len(note)) + bad = note[:k] + chr((ord(note[k]) + 1) % 128 or 1) + note[k + 1:] + p2, v2 = LG.verify_checkpoint(bad, ROSTER_BY_ID) + # An edit in the body loses every signer; an edit in one signature line loses that signer. + ok("checkpoints", p2 is None or len(v2) < len(verified), "an edited note still fully verifies: %r" % bad[max(0, k - 5):k + 5]) + + +def stress_mldsa(rng, rounds): + """ML-DSA-65 signs deterministically and verifies; a flipped bit anywhere, another message or another key fails.""" + for _ in range(max(3, rounds // 50)): + seed = os.urandom(32) + pk, sk = mldsa.keygen(seed) + msg = os.urandom(rng.randint(0, 100)) + sig = mldsa.sign(sk, msg) + ok("ml-dsa", len(pk) == mldsa.PK_SIZE and len(sk) == mldsa.SK_SIZE and len(sig) == mldsa.SIG_SIZE, "sizes") + ok("ml-dsa", mldsa.verify(pk, msg, sig) and mldsa.sign(sk, msg) == sig, "a signature does not verify or is not deterministic") + bad = bytearray(sig) + bad[rng.randrange(len(bad))] ^= 1 << rng.randrange(8) + ok("ml-dsa", not mldsa.verify(pk, msg, bytes(bad)), "a tampered signature verifies") + ok("ml-dsa", not mldsa.verify(pk, msg + b"x", sig) and not mldsa.verify(mldsa.keygen(os.urandom(32))[0], msg, sig), + "a signature verifies for another message or key") + ok("ml-dsa", not mldsa.verify(pk, msg, os.urandom(mldsa.SIG_SIZE)) and not mldsa.verify(os.urandom(mldsa.PK_SIZE), msg, sig), + "garbage verifies") + + +def main(): + ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + ap.add_argument("--seed", type=int, default=20261014, help="the random seed (default 20261014)") + ap.add_argument("--rounds", type=int, default=200, help="cases per property (default 200)") + a = ap.parse_args() + rng = random.Random(a.seed) + print("seed %d, %d rounds" % (a.seed, a.rounds)) + stress_canonical_json(rng, a.rounds) + stress_normalization(rng, a.rounds) + stress_notation(rng, a.rounds) + history = stress_corrections(rng, a.rounds) + stress_anchors(rng, history, a.rounds) + stress_merkle(rng, a.rounds) + stress_spotcheck(rng, a.rounds) + stress_bounds(rng, a.rounds) + stress_fingerprints(rng, a.rounds) + stress_zip(rng, a.rounds) + stress_packages(rng, a.rounds // 4) + stress_rights(rng, a.rounds) + stress_alignment(rng, a.rounds) + stress_addresses(rng, a.rounds) + stress_targets(rng, a.rounds) + stress_receipt_chains(rng, a.rounds) + stress_keys(rng, a.rounds) + stress_vrf(rng, a.rounds) + stress_proofs(rng, a.rounds) + stress_checkpoints(rng, a.rounds) + stress_mldsa(rng, a.rounds) + for k in sorted(COUNTS): + print("%-17s %6d checks" % (k, COUNTS[k])) + if FAILS: + print("\n%d failures (seed %d):" % (len(FAILS), a.seed)) + for f in FAILS[:60]: + print(" " + f) + sys.exit(1) + print("\nEvery property held.") + + +if __name__ == "__main__": + main() diff --git a/tools/validate.py b/tools/validate.py new file mode 100755 index 0000000..abafff3 --- /dev/null +++ b/tools/validate.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +"""Validate packages, or run the correction gate on proposals against a package. + +Non-normative tooling. +Usage: python3 tools/validate.py PACKAGE [PACKAGE ...] + python3 tools/validate.py --correction PROPOSALS PACKAGE +A package is a folder, or a zipped package (`.sct.zip`), which is unpacked under the rules of spec/12 §12.2 +before it is checked. Each is checked as spec/22 §22.2 describes, and each failure printed as +`package: where: rule: message`. +With --correction, PROPOSALS is a JSON file holding one proposed correction, or a JSON Lines file of several +applied in order. Each runs through the gate (spec/11 §11.4) against the package's current state, and the record +it would append to corrections.jsonl is printed, until one is refused. Nothing is written. +Exit status: 0 when everything is valid, 1 when something is refused, 2 for a usage error. +""" + +import argparse +import json +import os +import sys +import tempfile + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, ROOT) + +from tools.oracle import corrections, jcs, package # noqa: E402 +from tools.oracle.schema import Store # noqa: E402 +from tools.oracle.tree import Refusal # noqa: E402 + + +def read_proposals(path): + with open(path, encoding="utf-8") as f: + text = f.read() + try: + return [json.loads(text)] + except json.JSONDecodeError: + return [json.loads(ln) for ln in text.splitlines() if ln.strip()] + + +def validate_one(path, store, limit): + """The validation report of a package folder or a zipped package.""" + if package.is_zip(path): + return package.validate_zip(path, store, limit=limit) + return package.validate(path, store) + + +def main(): + lines = __doc__.splitlines() + ap = argparse.ArgumentParser(description=lines[0], epilog="\n".join(lines[5:]), + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--correction", metavar="PROPOSALS", + help="a JSON or JSON Lines file of proposed corrections to run through the gate") + ap.add_argument("--max-size", metavar="BYTES", type=int, default=package.ZIP_LIMIT, + help="refuse a zipped package that expands past this many bytes (default %d)" % package.ZIP_LIMIT) + ap.add_argument("packages", nargs="+", metavar="PACKAGE", help="package folders or zipped packages") + a = ap.parse_args() + if a.correction and len(a.packages) != 1: + ap.error("--correction checks proposals against exactly one package") + store, bad = Store(os.path.join(ROOT, "schemas")), False + for p in a.packages: + for e in validate_one(p, store, a.max_size).errors: + print("%s: %s: %s: %s" % (p, e["where"], e["rule"], e["message"]), file=sys.stderr) + bad = True + if bad: + return 1 + if not a.correction: + for p in a.packages: + print("%s: valid" % p) + return 0 + pkg = a.packages[0] + with tempfile.TemporaryDirectory() as tmp: + if package.is_zip(pkg): + pkg = package.read_zip(pkg, tmp, a.max_size) + state = package.read_state(pkg) + if any(n.get("withheld") for n in state.nodes): + print("%s: doc.policy.withheld: a package that withholds its text takes no corrections" % a.packages[0], + file=sys.stderr) + return 1 + for i, proposal in enumerate(read_proposals(a.correction), 1): + try: + state, record = corrections.gate(state, proposal, store) + except Refusal as e: + where = "%s:%d" % (a.correction, i) + (" " + e.node if e.node else "") + print("%s: %s: %s" % (where, e.rule, e.message), file=sys.stderr) + return 1 + print(jcs.dumps(record)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/vectors/README.md b/vectors/README.md new file mode 100644 index 0000000..18c288a --- /dev/null +++ b/vectors/README.md @@ -0,0 +1,169 @@ +# Test vectors + +Inputs and the exact outputs every implementation must compute. + +This folder is for three readers. +New to the problem? The first section says what a test vector is and why one exists. +Writing a reader, writer, converter or checker? Read the procedure for running a file, then use the table to find the vectors and chapters for the rule you are implementing. +Judging the specification? The last section says what the vectors establish and what they leave open. + +## What a test vector is + +Two programs can read a rule written in prose differently, and then the values they compute no longer match. +These formats store hashes of text, so a mismatch is visible and costly. +A hash is a short fixed-length fingerprint computed from data: the same data always gives the same hash, and in practice any change gives a different one. +These formats use SHA-256, written as 64 lowercase hexadecimal digits ([1.3](../spec/01-conventions.md#13-hashes)). +The same sentence gets two hashes when one program collapses runs of spaces before hashing and another does not, and the second program sees a change that never happened. + +A test vector removes the doubt. +It is one case: an input and the exact output that the specification requires for it. +An implementation passes a case when its own output for that input is identical to the expected one. +The vectors are normative, like the chapters: where a chapter and a vector disagree, the disagreement is a bug ([spec/README.md](../spec/README.md)). + +One case from `normalize.jsonl`, which pins the text normalization of [1.4](../spec/01-conventions.md#14-text-normalization-for-hashing): + +```json +{"id":"collapse","input":"a \t\n b","output":"a b","sha256":"c8687a08aa5d6ed2044328fa6a697ab8e96dc34291e8c2034ae8c38e6fcc6d65"} +``` + +The input is the letter a, a space, a tab, a newline, a space and the letter b. +The rule collapses every run of whitespace to one space, so the output is `a b`, and `sha256` is the SHA-256 of that output. + +JSON is a text format for structured data, and a file of one JSON value per line is called JSON Lines. +Each file holds one case per line, in canonical JSON, with an `id`, its inputs, and its expected outputs. +Canonical JSON is the one agreed way of writing a JSON value, the JSON Canonicalization Scheme of [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785), a numbered Internet standard (RFC means Request for Comments), plus the repository's own rules ([1.1](../spec/01-conventions.md#11-canonical-json)): no whitespace between tokens, object members in a fixed order, and numbers written one way. +The same data is always the same bytes when every file is written this way, so it hashes the same. + +A format's identifier, for example `scienting-id/1`, appears inside several cases. +The `scienting-` prefix is the formats' namespace; it has no connection to the name of this repository. + +## How to run a vector file + +Run the vectors in your own test suite, against your own implementation. +[docs/examples.md](../docs/examples.md#test-your-implementation-against-a-vector) shows the shape of a harness for `projections.jsonl`. +The procedure is the same for every file: + +1. + Read the file as UTF-8 (the standard Unicode text encoding) and split it at U+000A only. + `normalize.jsonl` contains a raw U+2028 (line separator) inside one case, so a reader that splits at every Unicode line break, such as Python's `str.splitlines()`, cuts that case in two. + Python's `for line in open(path, encoding="utf-8")` splits correctly. +2. + Parse each line as JSON. +3. + Find the inputs and the expected outputs of the case. + The table below says which fields are which, and the chapter it links defines the rule. + Only six files, `alignment`, `corrections`, `grading`, `resolve`, `rights` and `targets`, put the expected outputs under `expect`. + In the other nineteen the expected outputs are fields beside the inputs, such as `output`, `sha256`, `canonical` or `parsed`. +4. + Compute each output from the inputs with your implementation. +5. + Compare each computed output with the expected one. + Strings must be identical. + Objects and arrays are compared as values, which is how the reference checker compares them. +6. + Report every difference with the case's `id`. + +Some files change the procedure: + +- `canonical-json.jsonl` gives JSON text in `input_json`. + Parse its numbers as IEEE 754 doubles (the 64-bit floating-point numbers most languages use), as a JavaScript engine does. + The `numbers` case contains `123456789012345678901`, which a parser that keeps exact integers reads differently; the expected output is `123456789012345680000`. +- `projection-groups.jsonl` has no inputs of its own. + Each of its cases lists ids from `projections.jsonl` and names a field in which those cases must be equal (`same`) or unequal (`differ`). + Compute the field for each listed case and compare across the group. +- `fingerprints.jsonl` needs the download-stamp rules in [registry/stamps/scienting-stamps-1.json](../registry/stamps/scienting-stamps-1.json), which each case names in `rules`. +- `resolve.jsonl`, `grading.jsonl` and `targets.jsonl` name a package by a path from the repository root. + All three use `fixtures/packages/hale2026harmonic`. + +Several files also mix more than one kind of case, told apart by their fields. +`ids.jsonl` has minting cases and letter-first cases, `keyed.jsonl` and `signatures.jsonl` have a case for each derivation or record, `spotcheck.jsonl` has sample-size cases and one full sample, and `rights.jsonl` has stage checks (a `stage` field), backend checks (a `backend` field) and one combining case (neither). + +The reference checker in [tools/](../tools/README.md) runs all twenty-five files, together with the rest of the repository's checks: + +```sh +python3 tools/check.py --quick +``` + +It needs Python 3.14 and two packages, `jsonschema` and `cryptography`, and has no option to run one file. +It tests the reference implementation in `tools/oracle/` against the vectors. +It does not test yours. + +## What each file tests + +The table below uses a few terms that the chapters define: + +- A code point is one Unicode character; UTF-16 is an encoding that writes some characters as two units, so a JavaScript string offset can differ from a code-point offset ([1.5](../spec/01-conventions.md#15-character-offsets)). +- An HMAC is a hash computed under a secret key, so that someone without the key cannot recompute it ([5.8](../spec/05-hashes.md#58-keyed-hashes)). +- A Merkle root is one hash that commits to a list of items by hashing them in a binary tree ([8.5](../spec/08-fidelity.md#85-merkle-roots)). +- A page fingerprint is a hash of a page's text and images with download stamps removed, so two differently stamped downloads of one paper share it ([7.1](../spec/07-geometry.md#71-page-fingerprints)). +- The strict and lossy projections are two canonical forms of a sentence's text, one to certify that two readings agree and one to propose that they might ([5.3](../spec/05-hashes.md#53-the-strict-projection)). + +[docs/glossary.md](../docs/glossary.md) defines the rest. + +| File | Tests | Chapter | +| --- | --- | --- | +| `canonical-json.jsonl` | `input_json`, parsed with every number as an IEEE 754 double, and its canonical `output`. | [1.1](../spec/01-conventions.md#11-canonical-json) | +| `normalize.jsonl` | Normalization for hashing, and the SHA-256 of the result. | [1.4](../spec/01-conventions.md#14-text-normalization-for-hashing) | +| `ids.jsonl` | Minting payloads and node IDs, and letter-first encodings of digests. | [4](../spec/04-identity.md) | +| `notation.jsonl` | Each math source's canonical linear form, or null when it is complex. | [5.4](../spec/05-hashes.md#54-simple-notation) | +| `projections.jsonl` | One-sentence runs: plain, normalized, strict and lossy projections, complex keys and the three text values. | [5.3](../spec/05-hashes.md#53-the-strict-projection) | +| `projection-groups.jsonl` | Which cases must share, or must differ in, a value: H₂O in six spellings, cm⁻¹, 10⁻³, K_r, ligatures, the micro sign, "103" against 10³. | [5.3](../spec/05-hashes.md#53-the-strict-projection) | +| `offsets.jsonl` | Code-point spans and their UTF-16 equivalents. | [1.5](../spec/01-conventions.md#15-character-offsets) | +| `hashes.jsonl` | Every node of a small document, its own content and its five values. | [5.1](../spec/05-hashes.md#51-the-five-values) | +| `addresses.jsonl` | How addresses parse; null for invalid ones. | [6.1](../spec/06-anchors.md#61-addresses) | +| `keyed.jsonl` | The team key and its ID, an HMAC, page hashes, a page-derived key, and what someone without the paper cannot check. | [5.8](../spec/05-hashes.md#58-keyed-hashes) | +| `fingerprints.jsonl` | Pages as text lines, the stamp rules that fired, and the fingerprint; two downloads that must agree, and a change that must not. | [7.1](../spec/07-geometry.md#71-page-fingerprints) | +| `merkle.jsonl` | Receipt items and their Merkle roots. | [8.5](../spec/08-fidelity.md#85-merkle-roots) | +| `signatures.jsonl` | The RFC 8032 test vector; a receipt's record hash, signing payload and signature; `did:key` identifiers for an Ed25519 and an ML-DSA-65 key; and ML-DSA-65 (FIPS 204): NIST's key-generation case and a deterministic signature. | [8.4](../spec/08-fidelity.md#84-record-hashes-and-signatures) | +| `spotcheck.jsonl` | Seed payloads, seeds, sample sizes and samples. | [8.8](../spec/08-fidelity.md#88-spot-checks) | +| `bounds.jsonl` | Reviewer error bounds as reported. | [8.9](../spec/08-fidelity.md#89-reviewer-error-bounds) | +| `alignment.jsonl` | Two readings of a document, their pairs and their suspects. | [5.6](../spec/05-hashes.md#56-alignment) | +| `corrections.jsonl` | Each operation and refusal on a small document: the state before, the correction, and the record and state after, or the rule broken. | [11](../spec/11-corrections.md) | +| `resolve.jsonl` | Anchors made on the example paper's first reading, and how each resolves after its corrections. | [6.5](../spec/06-anchors.md#65-resolution) | +| `rights.jsonl` | Stage checks with policies and expiry, the combining rule, and backend conditions. | [14](../spec/14-rights.md) | +| `grading.jsonl` | Exercises, submissions and the grades they earn. | [19.4](../spec/19-exercises.md#194-grading) | +| `targets.jsonl` | The target set of targeted F3 for the example paper under each digit rule, given the anchored nodes. | [8.10](../spec/08-fidelity.md#810-targeted-f3) | +| `keys.jsonl` | Work keys: Scholar parts, identities, hash suffixes and document keys, with accented names, missing years and a collision. | [2.4](../spec/02-model.md#24-work-and-document-keys) | +| `proofs.jsonl` | RFC 9162 inclusion paths for every item of small trees, consistency proofs for every prefix, the empty root, and the example paper's history. | [8.5](../spec/08-fidelity.md#85-merkle-roots), [11.5](../spec/11-corrections.md#115-the-history-root) | +| `vrf.jsonl` | The VRF of spot-check seeds: RFC 9381's Example 16, two more inputs for its key, the example paper's seed, and proofs that must not verify (`beta` null). Bytes are hex. | [8.8](../spec/08-fidelity.md#88-spot-checks) | +| `checkpoint.jsonl` | A transparency-log checkpoint: the entries, their root, the signed note and its signers. | [23](../spec/23-log.md) | + +Resolve those paths against the files in that package only. + +## What the vectors prove, and what they do not + +The specification, and the vectors with it, are at version 0.1.0 ([0.3](../spec/00-introduction.md#03-format-identifiers-and-versions)). +The specification has 32 formats: 19 are `candidate` and 13 are `provisional` in [registry/formats.json](../registry/formats.json). +A candidate format changes only with a recorded reason and a new or changed vector ([22.5](../spec/22-conformance.md#225-stability)). + +A passing run shows one thing: for these inputs, your implementation computes the same values as the reference implementation in `tools/oracle/`. +That code computed the expected outputs, and `pixi run build` regenerates them ([tools/](../tools/README.md)). +The vectors hold 311 cases in all, some of them small: `hashes.jsonl` has one document, `alignment.jsonl` one pair of readings, `offsets.jsonl` two cases. + +The vectors do not show the following. + +- Conformance: the vectors are one part of the suite in [chapter 22](../spec/22-conformance.md#221-the-suite). + A conforming implementation must also accept every valid package in `fixtures/packages/`, and refuse every package in `fixtures/invalid/`, naming the rule it breaks if it can. + No vector tests package validation. +- Independent agreement: the only program in this repository that runs the vectors is the reference checker, and it uses the same oracle that produced them. + A rule that the oracle and the chapter both misstate would pass. + A separately written implementation that passes is evidence the repository cannot supply itself, and a disagreement between a chapter and a vector is a bug to report. +- Rules the vectors skip: + - `canonical-json.jsonl` has five cases, none for the repository's rule that a lone surrogate, `NaN` or an infinity has no canonical form. + - `merkle.jsonl` has roots for 1, 2, 3, 4, 5 and 7 items. + A receipt with no items is invalid ([8.5](../spec/08-fidelity.md#85-merkle-roots)), so no case has an empty list, although the RFCs it follows define a hash for an empty list ([RFC 6962](https://www.rfc-editor.org/rfc/rfc6962), [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162)). + - Thirteen formats are `provisional`, and only `grading.jsonl` carries any of their identifiers (exercise, submission and grade). + The chapters of the others define values that no vector pins, such as a dataset's content hash ([15](../spec/15-datasets.md)), the hash that confirms a digitization ([16](../spec/16-digitization.md)) and a checklist's content hash ([8.11](../spec/08-fidelity.md#811-checklists)). + They are expected to change as implementations gain experience ([0.4](../spec/00-introduction.md#04-status)). +- Reading a PDF: how text lines are extracted from a PDF is outside the specification; `fingerprints.jsonl` supplies the lines, so it tests the fingerprint function only ([7.1](../spec/07-geometry.md#71-page-fingerprints)). +- Faithful conversion: the vectors check what is computed from text, not whether a converter read the paper correctly. + The formats record such an error and make it checkable through corrections and receipts ([chapter 8](../spec/08-fidelity.md), [chapter 11](../spec/11-corrections.md)); the vectors do not detect it. +- Security: `signatures.jsonl` contains the RFC 8032 test vector and one receipt, so it checks that your Ed25519 and record hashing give the stated bytes. + The secrets in `keyed.jsonl` and `signatures.jsonl` are test values published in this repository; do not use them for anything real. + +A vector that rests on a building block defined elsewhere pins this specification's use of it. +Canonical JSON is RFC 8785 with added rules. +Receipts use a Merkle tree that follows RFC 6962 ([8.5](../spec/08-fidelity.md#85-merkle-roots)); RFC 9162 replaces RFC 6962 and defines the same tree. +The `node_hash` of a node is a different construction: a hash of the canonical JSON of `{own, children}`. +Here `own` is the node's own hash and `children` holds the `node_hash` of each child ([5.1](../spec/05-hashes.md#51-the-five-values)), and `hashes.jsonl` pins it. +The [comparison page](../docs/comparison.md) covers how these formats differ from JATS (Journal Article Tag Suite), TEI (Text Encoding Initiative), W3C (World Wide Web Consortium) Web Annotation and the other neighbors. diff --git a/vectors/addresses.jsonl b/vectors/addresses.jsonl new file mode 100644 index 0000000..076ec2e --- /dev/null +++ b/vectors/addresses.jsonl @@ -0,0 +1,17 @@ +{"address":"cornell1995second-saqk#k3m9q2a","id":"plain","parsed":{"key":"cornell1995second-saqk","node":"k3m9q2a","pin":null,"span":null,"store":null}} +{"address":"cornell1995second-saqk#k3m9q2a@4f1a0c","id":"pinned","parsed":{"key":"cornell1995second-saqk","node":"k3m9q2a","pin":"4f1a0c","span":null,"store":null}} +{"address":"cornell1995second-saqk#k3m9q2a@4f1a0c[12:57]","id":"span","parsed":{"key":"cornell1995second-saqk","node":"k3m9q2a","pin":"4f1a0c","span":[12,57],"store":null}} +{"address":"smithlab/cornell1995second-saqk#k3m9q2a","id":"store","parsed":{"key":"cornell1995second-saqk","node":"k3m9q2a","pin":null,"span":null,"store":"smithlab"}} +{"address":"dong2026machine-1ard.v2#k3m9q2a[0:0]","id":"span-no-pin","parsed":{"key":"dong2026machine-1ard.v2","node":"k3m9q2a","pin":null,"span":[0,0],"store":null}} +{"address":"cornell1995second-saqk.si#m2x8p4d","id":"si","parsed":{"key":"cornell1995second-saqk.si","node":"m2x8p4d","pin":null,"span":null,"store":null}} +{"address":"cornell1995second-saqk#b-p03-text-004","id":"alias","parsed":{"key":"cornell1995second-saqk","node":"b-p03-text-004","pin":null,"span":null,"store":null}} +{"address":"cornell1995second-saqk#k3m9q2a[57:12]","id":"bad-reversed","parsed":null} +{"address":"cornell1995second-saqk#k3m9q2a@4F1A0C","id":"bad-pin","parsed":null} +{"address":"k-0000#k3m9q2a[01:2]","id":"bad-leading-zero","parsed":null} +{"address":"cornell1995second-saqk#","id":"bad-no-node","parsed":null} +{"address":"Cornell1995-k3f9#k3m9q2a","id":"bad-upper-key","parsed":null} +{"address":"a/b/c-0000#k3m9q2a","id":"bad-two-stores","parsed":null} +{"address":"k-0000#k3m9q2a@4f1a","id":"bad-pin-length","parsed":null} +{"address":"cornell1995second#k3m9q2a","id":"bad-no-hash","parsed":null} +{"address":"cornell1995second-k3fi#k3m9q2a","id":"bad-hash-alphabet","parsed":null} +{"address":"cornell1995second-k3f#k3m9q2a","id":"bad-short-hash","parsed":null} diff --git a/vectors/alignment.jsonl b/vectors/alignment.jsonl new file mode 100644 index 0000000..98969aa --- /dev/null +++ b/vectors/alignment.jsonl @@ -0,0 +1 @@ +{"a":[{"complex":[],"container":"h","context":"heading","id":"a1","lossy":"methods","runs":[{"kind":"text","text":"Methods"}],"strict":"Methods"},{"complex":[],"container":"p1","context":"paragraph","id":"a2","lossy":"everybondwasscannedinstepsof0.01åarounditsminimum.","runs":[{"kind":"text","text":"Every bond was scanned in steps of 0.01 Å around its minimum."}],"strict":"Every bond was scanned in steps of 0.01 Å around its minimum."},{"complex":["tex:\\frac{a}{b}"],"container":"p1","context":"paragraph","id":"a3","lossy":"whereisthebondlength.","runs":[{"kind":"text","text":"where "},{"kind":"math","notation":"tex","source":"\\frac{a}{b}"},{"kind":"text","text":" is the bond length."}],"strict":"where  is the bond length."},{"complex":[],"container":"p1","context":"paragraph","id":"a4","lossy":"thefittedrateis103persecondatroomtemperature.","runs":[{"kind":"text","text":"The fitted rate is 10³ per second at room temperature."}],"strict":"The fitted rate is 10^{3} per second at room temperature."},{"complex":["tex:\\frac{c}{d}"],"container":"p2","context":"paragraph","id":"a5","lossy":"whereisthebondlength.","runs":[{"kind":"text","text":"where "},{"kind":"math","notation":"tex","source":"\\frac{c}{d}"},{"kind":"text","text":" is the bond length."}],"strict":"where  is the bond length."},{"complex":[],"container":"p2","context":"paragraph","id":"a6","lossy":"thissentencewasdroppedbythesecondreadingentirely.","runs":[{"kind":"text","text":"This sentence was dropped by the second reading entirely."}],"strict":"This sentence was dropped by the second reading entirely."},{"complex":[],"container":"p2","context":"paragraph","id":"a7","lossy":"thelastsentenceofthesectionisuniqueandlongenough.","runs":[{"kind":"text","text":"The last sentence of the section is unique and long enough."}],"strict":"The last sentence of the section is unique and long enough."}],"b":[{"complex":[],"container":"x","context":"paragraph","id":"b1","lossy":"methods","runs":[{"kind":"text","text":"Methods"}],"strict":"Methods"},{"complex":[],"container":"q1","context":"paragraph","id":"b2","lossy":"everybondwasscannedinstepsof0.01åarounditsminimum.","runs":[{"kind":"text","text":"Every bond was scanned in steps of 0.01 Å around its minimum."}],"strict":"Every bond was scanned in steps of 0.01 Å around its minimum."},{"complex":["tex:\\frac{a}{b}"],"container":"q1","context":"paragraph","id":"b3","lossy":"whereisthebondlength.","runs":[{"kind":"text","text":"where "},{"kind":"math","notation":"tex","source":"\\frac{a}{b}"},{"kind":"text","text":" is the bond length."}],"strict":"where  is the bond length."},{"complex":[],"container":"q2","context":"paragraph","id":"b4","lossy":"thefittedrateis103persecondatroomtemperature.","runs":[{"kind":"text","text":"The fitted rate is 103 per second at room temperature."}],"strict":"The fitted rate is 103 per second at room temperature."},{"complex":["tex:\\frac{c}{e}"],"container":"q2","context":"paragraph","id":"b5","lossy":"whereisthebondlength.","runs":[{"kind":"text","text":"where "},{"kind":"math","notation":"tex","source":"\\frac{c}{e}"},{"kind":"text","text":" is the bond length."}],"strict":"where  is the bond length."},{"complex":[],"container":"q2","context":"paragraph","id":"b6","lossy":"asentenceonlythesecondreadinghas,alsolong.","runs":[{"kind":"text","text":"A sentence only the second reading has, also long."}],"strict":"A sentence only the second reading has, also long."},{"complex":[],"container":"q2","context":"paragraph","id":"b7","lossy":"thelastsentenceofthesectionisuniqueandlongenough.","runs":[{"kind":"text","text":"The last sentence of the section is unique and long enough."}],"strict":"The last sentence of the section is unique and long enough."}],"expect":{"pairs":[{"a":"a1","agree":true,"b":"b1"},{"a":"a2","agree":true,"b":"b2"},{"a":"a3","agree":true,"b":"b3"},{"a":"a4","agree":false,"b":"b4"},{"a":"a5","agree":false,"b":"b5"},{"a":"a7","agree":true,"b":"b7"}],"suspects":[{"a":"a1","b":"b1","kind":"structure"},{"a":"a4","b":"b4","kind":"number"},{"a":"a5","b":"b5","kind":"equation"},{"a":"a4","b":"b4","kind":"join"},{"a":"a5","b":"b5","kind":"join"},{"a":"a6","b":null,"kind":"dropped"},{"a":null,"b":"b6","kind":"added"}]},"id":"two-readings"} diff --git a/vectors/bounds.jsonl b/vectors/bounds.jsonl new file mode 100644 index 0000000..d6030bc --- /dev/null +++ b/vectors/bounds.jsonl @@ -0,0 +1,8 @@ +{"approx":0.258865551,"bound":"0.258866","confidence":"0.95","errors":0,"id":"k0-n10","sampled":10} +{"approx":0.009936082,"bound":"0.009937","confidence":"0.95","errors":0,"id":"k0-n300","sampled":300} +{"approx":0.394163302,"bound":"0.394164","confidence":"0.95","errors":1,"id":"k1-n10","sampled":10} +{"approx":0.015714555,"bound":"0.015715","confidence":"0.95","errors":1,"id":"k1-n300","sampled":300} +{"approx":0.120614155,"bound":"0.120615","confidence":"0.95","errors":2,"id":"k2-n50","sampled":50} +{"approx":0.102253378,"bound":"0.102254","confidence":"0.95","errors":5,"id":"k5-n100","sampled":100} +{"approx":0.95,"bound":"0.950000","confidence":"0.95","errors":0,"id":"k0-n1","sampled":1} +{"approx":1,"bound":"1.000000","confidence":"0.95","errors":10,"id":"k10-n10","sampled":10} diff --git a/vectors/canonical-json.jsonl b/vectors/canonical-json.jsonl new file mode 100644 index 0000000..b04c853 --- /dev/null +++ b/vectors/canonical-json.jsonl @@ -0,0 +1,5 @@ +{"id":"sort-utf16","input_json":"{\"\\u20ac\": 1, \"\\ud83d\\ude00\": 2, \"a\": 3, \"\\ufb01\": 4}","output":"{\"a\":3,\"€\":1,\"😀\":2,\"fi\":4}"} +{"id":"numbers","input_json":"[0, -0.0, 1.0, 100.0, 72.10, 1E21, 1e-7, 0.000001, 123456789012345678901, -2.5e-5, 4.50e2]","output":"[0,0,1,100,72.1,1e+21,1e-7,0.000001,123456789012345680000,-0.000025,450]"} +{"id":"escapes","input_json":"{\"s\": \"tab\\tnl\\ncr\\rq\\\"bs\\\\ctl\\u0001del\\u007fnbsp\\u00a0slash\\/\"}","output":"{\"s\":\"tab\\tnl\\ncr\\rq\\\"bs\\\\ctl\\u0001delnbsp slash/\"}"} +{"id":"nested","input_json":"{ \"b\" : [ true , false , null ] , \"a\" : { \"z\" : \"\" , \"y\" : [ ] } }","output":"{\"a\":{\"y\":[],\"z\":\"\"},\"b\":[true,false,null]}"} +{"id":"strings-stay-unnormalized","input_json":"{\"cafe\\u0301\": \"e\\u0301\", \"caf\\u00e9\": \"\\u00e9\"}","output":"{\"café\":\"é\",\"café\":\"é\"}"} diff --git a/vectors/checkpoint.jsonl b/vectors/checkpoint.jsonl new file mode 100644 index 0000000..7e43370 --- /dev/null +++ b/vectors/checkpoint.jsonl @@ -0,0 +1 @@ +{"entries":[["receipt","npc15pn6675z5","37b3025b54c6397e5f8d400912b5788cd6ce203059cd9143e7d521c2cdbf2917"],["receipt","y2zw8ctg5s8dp","ae17f8866a05ca1b671d96b7758984e11ac694acd6743835f107cb513c7cc600"],["receipt","mvjmb94nz7rdh","a4dca8b492bf3e1b190f22e09de77713523e345526fd1b01c1186d0fe80d1cf4"],["receipt","q465jpwz8afhe","39218b2b73e853e2e66d8d4ce68cf7e155ca001f05ee4da5942a8d9b63b216bc"],["revocation","pcbhtpwvysgq6","9062e3ab737ecc2e6d487d2076ee27f764be60f06ad01f1ad103d708d466e56a"],["receipt","gx2s84z9jf9xv","5ee8b2827d327a7bbcacb08fd19b9523fad83ebf6c29350d5ce7ca30bf5ce388"],["receipt","mg18668nzxvap","4c80506322bfeed5649cfab303959e4ccf0aa0e594995ee6fd5ad59f9d3ee6a7"],["receipt","yt70fcc3qm0xb","2ad1c0f63077a03ab1cce01e6235734577d0b072b90ebab2f7db7fd481ccee2c"],["roster","smithlab","782c5e68f4e4f9918e69b7a44b108d9d70c89a289981acff3d25300ec8373c15"]],"id":"smithlab","note":"scient.ing/log/smithlab\n9\nGa0n103p3Gl136z6XWmM92kGvsvMYGXlk+ijjX4KWiA=\n\n— ana dBv7wtCAdNnczkCO5KwtrmDvtWUVPRusBSuLPeBDQoLZi9Hm34IHuNjvnjyPEar5afNf7xqcDtokk2XZEP31uJMVuwE=\n— wit h7ghDsJGkhWLaPO7+TIZQUenslhiQh/E/TKWU4ddphpFcuylQBZM2kG/o8H1nyPfUT0MkbvnFqPFfHPH3OaN5W1EwAI=\n","origin":"scient.ing/log/smithlab","root":"19ad27d74de9dc6975dfacfa5d698cf76906becbcc6065e593e8a38d7e0a5a20","signers":["ana","wit"],"tiles":["tile/0/000.p/9","tile/entries/000.p/9"]} diff --git a/vectors/corrections.jsonl b/vectors/corrections.jsonl new file mode 100644 index 0000000..399e1a3 --- /dev/null +++ b/vectors/corrections.jsonl @@ -0,0 +1,29 @@ +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"find":"42.0","op":"replace","reason":"Vector.","replace":"42.5","target":"jvnys4s"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"307cdef8d5f3588c7c53e5a240d4b783ace86b546f90f1303f7cf6ead8b45eee","id":"s0fn2fj","kind":"document","match_hash":"7e518193f164955e7e1205873f30a8d194afc803781f7b6f7809a70add0b644f","node_hash":"2ac029bf3f4a916b9104c447e87e382fc49aeaf51e7860fecc2ea3926c70a22b","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"f79b4988b957d68c5d3737e422d036319aec6e712a6bbdc8440c66442c6e439e"},{"align_key":"7f41a785f070a6215cfcce68bfe1a1338eb1d0254f9489144e337cb3282b97e8","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"ee940b24d902afdb8975216bbbdf24fc8d78448952a1d616b6a3a8bca19ff797","node_hash":"6bc0ae46cd2e6d1056cca5829f72851f1d3dfcd0ad5e938f641785bee4aee98d","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"ac9bb67e4905d3e0e6eca791434c5c78c95d93496a7828b336ab2ddfec201c16"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"779d7967a4e24ebefbf9afca6731484b2831a71c44bd28b69d2df0501cc05a2f","id":"ytp1e5n","kind":"paragraph","match_hash":"9170b6f6f6108138330252801d45f6e50667941c6d8bbb50ee8e2506ee9a8aec","node_hash":"f8f27af77730e01ebd876447a2dee0a05747e4c252f8324d2139d2c16db79a50","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"a7c03223ac633d843f09b99f10bfe2b1ac93c48d92f1ce2bee370193c0dc8bab"},{"align_key":"2584e81a8f1bf4b1dbbe7b71d1fb29393026895cfa782b35064a2f3ad1cf890a","content":[{"kind":"text","text":"The value is 42.5 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"fa01fe9148af8b6eee1cbf001af30288929e9ac93b44de562569d006e046f277","node_hash":"ecbde59d339e26fa6a9ff0a48d820b915f791c0d91b419f4ad878a969331c076","ord":0,"own_hash":"40442b4483a236a2683b0d30e646f4f1b4f8cf573574fc06a76cefaf8849d265","parent":"ytp1e5n","text_hash":"fa01fe9148af8b6eee1cbf001af30288929e9ac93b44de562569d006e046f277"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"ecbde59d339e26fa6a9ff0a48d820b915f791c0d91b419f4ad878a969331c076","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"find":"42.0","format":"scienting-correction/1","id":"g0nx6qv9bq88q","index":1,"op":"replace","path":["s0fn2fj","b9wp3tt","ytp1e5n"],"reason":"Vector.","replace":"42.5","target":"jvnys4s","touched":["jvnys4s"]}},"id":"replace-digit"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"find":"42.0","op":"replace","reason":"Vector.","replace":"42.5","target":"jvnys4s"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.digits"},"id":"replace-digit-no-crop"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"find":"second","op":"replace","reason":"Vector.","replace":"later","target":"j663d4h"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"d5d0d7484318a8bbb9ff86e72db046272df3de603cd66887e5e36ac5e346b7b1","id":"s0fn2fj","kind":"document","match_hash":"93f6f7e23166833034b23b9b3022d67440822f938c192264e97599687264ee2b","node_hash":"015f640ad2dae6fb1b737cc7675d77f7cd8f1a541f4c28671528e05cb7c15288","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"76d2d3127a13daffec6418162db302f089043973b5ff98c0ad8b7cd5b37116fe"},{"align_key":"ffdcc21ef1e1688586f97ee07e3fe67a3f6c3c145ed22bdb86696b3c10fc4118","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"4aa5b3e8da313ac2c0ca4cb1f324e5bde4ecf70b16d6ec9df9e64c59ff88d5be","node_hash":"42bfaf1ed58b27269e230020ef79a45a8073b1a5861f05f9b4c807a10b4049b0","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"5e2a8f77bb3b78aa1c322d063368b7f74728df621421eb68cef5813ff2951e24"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"e2ffdc15a0aedd399bb1289258ce99f80f764cfb4124c273c5f5635884c9a05b","id":"exq1ter","kind":"paragraph","match_hash":"67882c3dc9b34613d96420fd3ca430b8be29013086f08f4ec203460f7b74ed04","node_hash":"9fe14a64167feee947551a33ebbe4f45ee8f242fa5f6d7f8b3c1ca6419efcb61","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"67882c3dc9b34613d96420fd3ca430b8be29013086f08f4ec203460f7b74ed04"},{"align_key":"58ef15516c7e769fe65626153c05a0f99a693959c9efe141b1d3b05e5d45751e","content":[{"kind":"text","text":"A later paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"08cc4ab6f3ade7710e5f7fac5675ad9e4b6ec3eed4385dbddc01d3266b197860","node_hash":"7638ac33bece08d53c97170c50a2d42759fa8ae6970c27635f343b95c9190f7a","ord":0,"own_hash":"6681b0147e9aef501504638010d88c9d07a81fb66ead3e6bc21549a04d296bad","parent":"exq1ter","text_hash":"08cc4ab6f3ade7710e5f7fac5675ad9e4b6ec3eed4385dbddc01d3266b197860"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"7638ac33bece08d53c97170c50a2d42759fa8ae6970c27635f343b95c9190f7a","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","evidence":[{"by":"ana","kind":"person"}],"find":"second","format":"scienting-correction/1","id":"bv86h42gkhz3a","index":1,"op":"replace","path":["s0fn2fj","b9wp3tt","exq1ter"],"reason":"Vector.","replace":"later","target":"j663d4h","touched":["j663d4h"]}},"id":"replace-word"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"find":"0","op":"replace","reason":"Vector.","replace":"1","target":"jvnys4s"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.find"},"id":"replace-not-unique"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"find":"300 K","op":"replace","reason":"Vector.","replace":[{"kind":"math","notation":"tex","source":"300\\,\\mathrm{K}"}],"target":"jvnys4s"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"e5c0a8bc46dcfaa863a8b1b8b47cf1ce17f92fbe843c24809efe7bc06c61dd36","node_hash":"5122d3f8f1b589e14b4530d46015d6855a3f2271a6beafe2c289f35fe88d08bc","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"230751a057cfb05c90472d0519b1494bceb8e97935b0bb25d2c84f5df88d5bd3"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"6ed7a9811ba0ea36c025e36e27cb8217983db65052156998b8420fb7393e7676","node_hash":"58c71d717603ddfe949573ab616b9c58910e72632951f8d2485fa1212259500a","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"9181fb7a9952168f1abc94771d7101fa4563403432448094f8f5f0532f093a9b"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"780246e820ddb4784bee63ad5f3c049e9cfad6c761b7e75981826004bb3952b9","node_hash":"a5336a0ec43455f6077c8fa5d166240b79a677bd3fc8f12f2934ce43951c83e0","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"ffcfd4089d7a6bf62d23c41c1e99db8a44a1e2f7c45c1af93986f55a5464afa9"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at "},{"kind":"math","notation":"tex","source":"300\\,\\mathrm{K}"},{"kind":"text","text":"."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"f506115d79413340915fbd30daadfefe57d9e44e01ecb19401d78e8b77b04a13","node_hash":"f021a9d2435fcf11eb1babafeaec52991d37c997d4ca312d50a58bc18ab10d74","ord":0,"own_hash":"b4a20ac47e1a725076b316d9fb8822d09b6a0eabc1218eb2e826999ecbed53bb","parent":"ytp1e5n","text_hash":"f3ee4cc22182a9b3809ef1bf269dbad11ba7c93835503d96b2ed97cf9d142501"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"f021a9d2435fcf11eb1babafeaec52991d37c997d4ca312d50a58bc18ab10d74","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"find":"300 K","format":"scienting-correction/1","id":"pq85w0xrfg7aq","index":1,"op":"replace","path":["s0fn2fj","b9wp3tt","ytp1e5n"],"reason":"Vector.","replace":[{"kind":"math","notation":"tex","source":"300\\,\\mathrm{K}"}],"target":"jvnys4s","touched":["jvnys4s"]}},"id":"replace-runs"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"offset":8,"op":"insert","reason":"Vector.","run":0,"target":"rsw24qc","text":"only "},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"41a48a1f6c072bced379281d83bd875c18dfd34dc49ebc199bac497801a8b11d","id":"s0fn2fj","kind":"document","match_hash":"727a0da7d0c63834ce7242b5ccec3900513af7e3b25af81b01f0465a89424421","node_hash":"f51cc351984636bb1a71f58ae9af5c7c7c38136b4eab26a98006a86e3419c049","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"320f3fde695d79169292cefb68b14bed141c5ab63f3e9d589944f55ff4da0c3c"},{"align_key":"82285464d23f37d25a5aeeaca0820b253cf60d660ea1711dab0f21c03fd956d1","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"a97e2212e1985ef783fb936b5fef3df1a1eb3747696c5610c5c3c94dd1b3926a","node_hash":"b773bc4742751d1154486c2233c49b3293c50a106462c1fb4d3aa189e92ae4ca","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"19dae57535f85e33aa21255c80ac56b2866c3a07b5897cf0c627009320c80219"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"4426408fb036372fdcf34395f08c667faed4d165b2885574ae2989230cfcd366","id":"exq1ter","kind":"paragraph","match_hash":"945c1a5609cd53e380f766ffd5777928e9a0a34317d53f0ffcb3906b4c4f094b","node_hash":"ebac9e474a5e9faeb4964ee7654e2cca938e161723bbfa6de281dd79f5c5ac16","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"945c1a5609cd53e380f766ffd5777928e9a0a34317d53f0ffcb3906b4c4f094b"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"e90693965ecebdc9ee2c319315dda9cfffe6d67a0308a5991421300697b0209c","content":[{"kind":"text","text":"It ends only here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"064f49112344bfcd430112b87384d6933a8a783c8ff8d7cddc3eb620cadee476","node_hash":"12c5bbc6dbeab7ca663098bd43232161665be1fe5a8ff7294a1be947398acf8d","ord":1,"own_hash":"ab57bab359f24cc15245ee7e245f174d5eebf61ed7e24091ede26c95014bb8fb","parent":"exq1ter","text_hash":"064f49112344bfcd430112b87384d6933a8a783c8ff8d7cddc3eb620cadee476"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"12c5bbc6dbeab7ca663098bd43232161665be1fe5a8ff7294a1be947398acf8d","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"format":"scienting-correction/1","id":"vq1xbna4kxw86","index":1,"offset":8,"op":"insert","path":["s0fn2fj","b9wp3tt","exq1ter"],"reason":"Vector.","run":0,"target":"rsw24qc","text":"only ","touched":["rsw24qc"]}},"id":"insert-text"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"offset":8,"op":"insert","reason":"Vector.","run":0,"target":"rsw24qc","text":"only "},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.evidence"},"id":"insert-text-no-crop"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"offset":0,"op":"insert","reason":"Vector.","run":7,"target":"rsw24qc","text":"x"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.insert"},"id":"insert-text-bad-run"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"node":{"content":[{"kind":"text","text":"A dropped sentence."}],"kind":"sentence"},"op":"insert","parent":"exq1ter","place_after":"j663d4h","reason":"Vector."},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"6ec26beeb8a65c2a45fe92187cb014aa12458c923834b1e2a224839175ff978a","id":"s0fn2fj","kind":"document","match_hash":"505eb15ffd9dae39efc48d382547fe95b0c06ebeab536a9ba3987caec136d72a","node_hash":"ca45df06696f76bda0cb5e9dc625f207969d116d38c0ccfbdb9492cb6fa9db86","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"7b8f52695e653922bd53599a4dd170145e9736ebb582aff1142c0e2925410643"},{"align_key":"376a90f437df93f81485a5965637d40e584c94c9b16020be00bc20d2ff914720","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"db9b2be0e3700a6cfdd638ae1504d315b286746d7eade11212d8c3e1319f7b79","node_hash":"6456edcab0e21338dc4fbf900f9173d83c2a958365ffc519b26bc96269636b2a","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"6ee72cbdd5d3fb25cdfe80488b78ef6adeca4cf1a8740712c5f6e95fcf480991"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"447cf4606eaf26ea5e0c2e853d369fd35557361e701c7176450c015d66dfd9b4","id":"exq1ter","kind":"paragraph","match_hash":"48ca423e488af5806237fc4f81200941bed73b6e49a116a08b8be7fc21a39529","node_hash":"2057a40d06bbdf67d40bee4e0c1fc550233e9c49c3f46237f920571129ff5ae6","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"48ca423e488af5806237fc4f81200941bed73b6e49a116a08b8be7fc21a39529"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"06f7b55ab26a52c8a75a5206105f3eacd8b91ed37399d6507d36712295ed9bca","content":[{"kind":"text","text":"A dropped sentence."}],"id":"tesfc78","kind":"sentence","match_hash":"67f0bb4b7a714ef1ecbf8fe70ec014122586ae104fa09ade1b83dd293f970251","node_hash":"74b9823a10437fb783f5b6018e6002ccce5ec2def03c945c9ab4a479eda7675d","ord":1,"own_hash":"adb284d8e83512c418b112fc1afe66e695bab257542f0daf03c7430402ec841f","parent":"exq1ter","text_hash":"67f0bb4b7a714ef1ecbf8fe70ec014122586ae104fa09ade1b83dd293f970251"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":2,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"74b9823a10437fb783f5b6018e6002ccce5ec2def03c945c9ab4a479eda7675d","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":null,"created":["tesfc78"],"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"format":"scienting-correction/1","id":"jva6d5hd493eh","index":1,"node":{"content":[{"kind":"text","text":"A dropped sentence."}],"kind":"sentence"},"op":"insert","parent":"exq1ter","path":["s0fn2fj","b9wp3tt","exq1ter"],"place_after":"j663d4h","reason":"Vector.","target":"tesfc78","touched":["tesfc78"]}},"id":"insert-node"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"delete","reason":"Vector.","target":"exq1ter"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[{"id":"exq1ter","kind":"retired","node_kind":"paragraph","rev":1,"successor":null},{"id":"j663d4h","kind":"retired","node_kind":"sentence","rev":1,"successor":null},{"id":"rsw24qc","kind":"retired","node_kind":"sentence","rev":1,"successor":null}],"nodes":[{"align_key":"2fadd2c2db90afd55fa1882a8b75c77f2b3c42ddf904ecc82cf02511b4c59263","id":"s0fn2fj","kind":"document","match_hash":"8287586b5d9b9125cef727ae54eff914c320931ab2a33fdb73a3511dd4f33827","node_hash":"acd4e85790544639cb1f5c134ddcb26368e9b8106f9f2411ab51e58dc55a20fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"6ada36f2dab47e5ef92bc8329d62c5cf576c5eb18587997d0ab151200ab87adf"},{"align_key":"80fa7df5fffafbc399fa56c13bd39d03698d187ff007d91ccf495c6d20161f65","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"f9f02fe3049dcbedd1e3f63f5a9a60306b2ab2501de9861ed37335e629bb50e4","node_hash":"d1e3e13596250d2430ae8bb60a71ebf5876461188a7864f97a363e9c5da7e4ea","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"d37b64cbae95acbde780dbd179569d4063554ede47c5e43c2a981ca6db5200f7"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":2,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":null,"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","evidence":[{"by":"ana","kind":"person"}],"format":"scienting-correction/1","id":"znfvk0vcp0rvj","index":1,"op":"delete","path":["s0fn2fj","b9wp3tt"],"reason":"Vector.","retired":["exq1ter","j663d4h","rsw24qc"],"target":"exq1ter","touched":["j663d4h","rsw24qc"]}},"id":"delete"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"delete","reason":"Vector.","target":"ytp1e5n"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.digits"},"id":"delete-digits-no-crop"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"offset":13,"op":"split","reason":"Vector.","target":"jvnys4s"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"b237e0c1e72fd4dd0c9b75a06a0e92665ec76633277952267fda0b94e48947ae","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"83adf57207718f6fb4f7ff7fe78c94a2c92936bba2d49b24180059dba9fea5b1","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"fc8f3d877b575812a886496772089b4022dc23eaeca53623441155144f7c5816","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"f29ffbc41756b5d6b65f2d95aced9241d9e6f6cbc0f3095c79654ca5fb4842d7","content":[{"kind":"text","text":"The value is"}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"f3c3316e32a5fc734f072184962e4efc69fe6ce534c6467ea28d5d216418ce3f","node_hash":"5106bd7f918b6eef99a4137e9c7951fb819924a261949e3ba43b813b76b68b21","ord":0,"own_hash":"39642e0f2675dc38f33e54d6b5077b89b862150e6475ede5b75043b66031f4f7","parent":"ytp1e5n","text_hash":"f3c3316e32a5fc734f072184962e4efc69fe6ce534c6467ea28d5d216418ce3f"},{"align_key":"e796489e949f8967be49d1a89d23b50ee1cbedd815124b4583d9c9cfcd26a68b","content":[{"kind":"text","text":"42.0 at 300 K."}],"fidelity":"F2","id":"x9ntkgx","kind":"sentence","match_hash":"bdcb3ae4f656f9f1886cb9ae8fe2d2265bb3c9ffa240dc4dd0c4b420f7b85773","node_hash":"cb0487cb9b17b048c442a1167152cccf7f62107283211bc8474569831f2ba245","ord":1,"own_hash":"a3145828b095eed04855f0eb65e18f6391acb3cb64e4a2c5776f56faa59444c8","parent":"ytp1e5n","text_hash":"bdcb3ae4f656f9f1886cb9ae8fe2d2265bb3c9ffa240dc4dd0c4b420f7b85773"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":2,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"5106bd7f918b6eef99a4137e9c7951fb819924a261949e3ba43b813b76b68b21","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","created":["x9ntkgx"],"evidence":[{"by":"ana","kind":"person"}],"format":"scienting-correction/1","id":"x6b2cda1cxn48","index":1,"offset":13,"op":"split","path":["s0fn2fj","b9wp3tt","ytp1e5n"],"reason":"Vector.","target":"jvnys4s","touched":["jvnys4s","x9ntkgx"]}},"id":"split"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"offset":6,"op":"split","reason":"Vector.","target":"mzwwhxj"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.split"},"id":"split-inside-xref"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"joiner":" ","op":"merge","reason":"Vector.","target":"j663d4h","with":"rsw24qc"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[{"id":"rsw24qc","kind":"retired","node_kind":"sentence","rev":1,"successor":"j663d4h"}],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"287c65a74c12e2ed007bfd86932005b7aebf2229683b15cbc7eef9b2e4c77d62","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"5a3cc449a5ec23c0f4957121ea94e8e209cc786ddeff0de62e1c9b20095d489c","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"868f0f5127954d4bacc42894944fbf09775dc571a88a0297d9687b29aa6a7cc6","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","content":[{"kind":"text","text":"A second paragraph. It ends here."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"74e8812b1beec14ea501ca218257c10b24318e264f7e2d34f19b1e8b8c731ab7","ord":0,"own_hash":"deace9c5c4208013043856b9bf910e8b92e2cb74f5a83d098004c5cb242ce6a0","parent":"exq1ter","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"74e8812b1beec14ea501ca218257c10b24318e264f7e2d34f19b1e8b8c731ab7","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","evidence":[{"by":"ana","kind":"person"}],"format":"scienting-correction/1","id":"s82rnjy7xsbx8","index":1,"joiner":" ","op":"merge","path":["s0fn2fj","b9wp3tt","exq1ter"],"reason":"Vector.","retired":["rsw24qc"],"target":"j663d4h","touched":["j663d4h","rsw24qc"],"with":"rsw24qc"}},"id":"merge"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"merge","reason":"Vector.","target":"jvnys4s","with":"j663d4h"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.merge"},"id":"merge-not-adjacent"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"move","parent":"ytp1e5n","place_after":null,"reason":"Vector.","target":"rsw24qc"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"30da8787f3792df5a4e75f1d87d273d7aff410e107b663b9fd383a975ff9177c","id":"s0fn2fj","kind":"document","match_hash":"07eb80f34efabcea897cd2b949e95443e5be8ec044b8fe2655e86b7abd9c4c37","node_hash":"a63c9607c700b0744120ecf44bc60ce01bd07affdc250ec432d567a805a5f2a3","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"a14e294152535392e6433d3f37ef2fbda2b20ec8f75a50ded71d270579590ed4"},{"align_key":"37e0f3f45a1d705dcd2a82ba5087c26048f8bc1697e3314087672219cf368eb9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"4ff38d2aa4195ffb3bafcb6871ed1f73ebdb415b28f343a59961306c95f303ad","node_hash":"12bcf59558b1919b4f03b724f93e10567c3952760f16d080f29745df60e1cf3c","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"ac4f8c912c0b7647c3328c8cb1e6477eb2022a06704953640804f457c7371bd7"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"9a3f0cd42b75fa281cb12c86f8956d84df0a5453e3cfc87e5e7bfaafef35b239","id":"ytp1e5n","kind":"paragraph","match_hash":"4c9c6e087af631d07b0a9307a03c9dad2b6358c12c1f4893cec59c6d34e1a693","node_hash":"07fec7572a5b5d0ae766fea87adc065fb9edf8772b78a3f61a9fca7eccaa868a","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"6e46e1038a90fb0ecd345eb2c1aa93f73eea29976417c54d03926ddc6a9c3861"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":0,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"ytp1e5n","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":1,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":2,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","id":"exq1ter","kind":"paragraph","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"f70e1bc04609eb6272efbf2f8844c67165bccc1e9df8be4e62d9c826e0e34592","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","evidence":[{"by":"ana","kind":"person"}],"format":"scienting-correction/1","id":"v52xb4repa5qw","index":1,"op":"move","parent":"ytp1e5n","path":["s0fn2fj","b9wp3tt","exq1ter"],"place_after":null,"reason":"Vector.","target":"rsw24qc","to_path":["s0fn2fj","b9wp3tt","ytp1e5n"],"touched":["rsw24qc"]}},"id":"move"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"move","parent":"exq1ter","place_after":"rsw24qc","reason":"Vector.","target":"rsw24qc"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.move"},"id":"move-after-itself"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"kind":"footnote","op":"reclassify","reason":"Vector.","target":"exq1ter"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"5ebd5766f15e3bb2536d5c0c8e82bcd14ea009b75ab88b00c64a11773a82ec06","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"badb8bcb6f7dcae6f61233fdaf2441194ad104dab0c730e5c7ec170de30fc8a6","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"footnote","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"3728fa844134297833f690c1fb31e16c068f03b82c2c0d31b1b92421e439d430","ord":2,"own_hash":"0b05f397194cbe6331259a27e326547f7199864e9e6648a720fd7e1a07bfd97d","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"3728fa844134297833f690c1fb31e16c068f03b82c2c0d31b1b92421e439d430","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","evidence":[{"by":"ana","kind":"person"}],"format":"scienting-correction/1","from":"paragraph","id":"z59g92d162aat","index":1,"kind":"footnote","op":"reclassify","path":["s0fn2fj","b9wp3tt"],"reason":"Vector.","target":"exq1ter","touched":["j663d4h","rsw24qc"]}},"id":"reclassify"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"kind":"quote","op":"reclassify","reason":"Vector.","target":"exq1ter"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"doc.tree.child"},"id":"reclassify-blocks"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"kind":"paragraph","op":"reclassify","reason":"Vector.","target":"jvnys4s"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.reclassify"},"id":"reclassify-bad"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"label":"2","op":"relabel","reason":"Vector.","target":"b9wp3tt"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"4ba942dec75d85f4a8d9690609d92b7ac810b0cf4d1d7fc3b89e2b1924bd4634","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"2","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"41800aff40fe974cccee57152b0cc577ac0b6a48698fa25748957f76c5806668","ord":0,"own_hash":"705939943052c43c01c27e7d40d86f6a5fc3af71539ba76d44369885429e40c3","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"41800aff40fe974cccee57152b0cc577ac0b6a48698fa25748957f76c5806668","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"format":"scienting-correction/1","from":"1","id":"rw857d4y4sjcp","index":1,"label":"2","op":"relabel","path":["s0fn2fj"],"reason":"Vector.","target":"b9wp3tt","touched":[]}},"id":"relabel-section"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"label":null,"op":"relabel","reason":"Vector.","target":"b9wp3tt"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"6ffe6b4f4e48d7553ff7e794d23ef024b0fa9d1c4c8e8fd864b38bbddf401651","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"af168d111a983837d3ea68e3af8cdc3a5a43eedf771a7bf403e9a839b7a96253","ord":0,"own_hash":"28e53f4a7c9afa404ebda4905d5adbbbe6e75b6a782e35d958a18f7a3bec10f9","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"af168d111a983837d3ea68e3af8cdc3a5a43eedf771a7bf403e9a839b7a96253","at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"before":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"format":"scienting-correction/1","from":"1","id":"j97fqb83gcy9c","index":1,"label":null,"op":"relabel","path":["s0fn2fj"],"reason":"Vector.","target":"b9wp3tt","touched":[]}},"id":"relabel-remove"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"label":"Table 2","op":"relabel","reason":"Vector.","target":"tb49qpc"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.digits"},"id":"relabel-digit-no-crop"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","attr":"colspan","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"set","reason":"Vector.","target":"f463wj7","value":2},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a223385051fa4d5639b996b3b2a5f085a3309f109a48d810d72c3036f7b16241","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"cd2d440303020bc6bf109779788f89db200d3b0c97d4ec8fd35ec32728d45cd2","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"b00cf4c71fb7846fb7460cf90bca0f099c2e1d7f281e561fe8c31cb200f258e6","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"a174489307106f42f57f221f42b257e2c5352cd990a4727acf413e07ab67ad5e","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"2da2b198d919729f2c369e0d460c0bd5264e04c646540aeed3f56eedb1a063c8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":2,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"e80bd4d8de9183a590a5ad87d10ec54ce1a91843cc9fd6fab328e7e4100387dc","ord":1,"own_hash":"ab04fb9fa7c7004bbd07df12033475ff135b7dbe9aec0403e659595540d801a4","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"e80bd4d8de9183a590a5ad87d10ec54ce1a91843cc9fd6fab328e7e4100387dc","at":"2026-10-11T12:00:00Z","attr":"colspan","author":{"key":"ana"},"before":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","evidence":[{"by":"ana","kind":"person"}],"format":"scienting-correction/1","from":1,"id":"y8sfdmfkmqxnh","index":1,"op":"set","path":["s0fn2fj","b9wp3tt","tb49qpc","dmsstkg","r3e7hfs"],"reason":"Vector.","target":"f463wj7","touched":["f463wj7"],"value":2}},"id":"set-colspan"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","attr":"colspan","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"set","reason":"Vector.","target":"f463wj7","value":"2"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"doc.node.attrs"},"id":"set-bad-value"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","attr":"level","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"set","reason":"Vector.","target":"f463wj7","value":2},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"correction.set"},"id":"set-not-settable"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"kind":"crop","sha256":"4839e386aceece09ab1602a8291e072f2cc4e322e44ef458666f9b89c4ed6e54"}],"node":{"content":[{"kind":"text","text":"Junk."}],"foo":1,"kind":"sentence"},"op":"insert","parent":"exq1ter","place_after":"j663d4h","reason":"Vector."},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"doc.node.schema"},"id":"insert-node-junk"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"key":"ana"},"evidence":[{"by":"ana","kind":"person"}],"op":"delete","reason":"Vector.","target":"af5b51r"},"doc":"tiny2026tiny-j4qm","expect":{"refusal":"doc.table.header"},"id":"delete-header-cell"} +{"before":{"ids":[],"nodes":[{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","id":"s0fn2fj","kind":"document","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","id":"exq1ter","kind":"paragraph","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","ord":0,"own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","parent":"exq1ter","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"rev":0},"correction":{"at":"2026-10-11T12:00:00Z","author":{"model":{"name":"example-model","parameters":"998b5161e39e01c8bc43ef81ec89141e15b7ea53b2e936707920a6097dbcb2c5","processor":"local","prompt":"9cc338fba7c62db7266f530cb555a5ee36910d41a0120a3fe7fd7de1944d0931","provider":"Example Models (illustrative)","version":"2026-09","weights":"504b2d340045b92c22682b60020c21103aae7ff41172bb632fbe305eb4af9b5e"},"run":"illustrative-run-7"},"evidence":[{"by":"ana","kind":"person"}],"find":"second","op":"replace","reason":"Vector.","replace":"later","target":"j663d4h"},"doc":"tiny2026tiny-j4qm","expect":{"ids":[],"nodes":[{"align_key":"d5d0d7484318a8bbb9ff86e72db046272df3de603cd66887e5e36ac5e346b7b1","id":"s0fn2fj","kind":"document","match_hash":"93f6f7e23166833034b23b9b3022d67440822f938c192264e97599687264ee2b","node_hash":"015f640ad2dae6fb1b737cc7675d77f7cd8f1a541f4c28671528e05cb7c15288","ord":0,"own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","parent":null,"text_hash":"76d2d3127a13daffec6418162db302f089043973b5ff98c0ad8b7cd5b37116fe"},{"align_key":"ffdcc21ef1e1688586f97ee07e3fe67a3f6c3c145ed22bdb86696b3c10fc4118","attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","match_hash":"4aa5b3e8da313ac2c0ca4cb1f324e5bde4ecf70b16d6ec9df9e64c59ff88d5be","node_hash":"42bfaf1ed58b27269e230020ef79a45a8073b1a5861f05f9b4c807a10b4049b0","ord":0,"own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","parent":"s0fn2fj","text_hash":"5e2a8f77bb3b78aa1c322d063368b7f74728df621421eb68cef5813ff2951e24"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","id":"vet7k0e","kind":"heading","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","ord":0,"own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","parent":"b9wp3tt","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","ord":0,"own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","parent":"vet7k0e","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","id":"ytp1e5n","kind":"paragraph","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","ord":1,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"},{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","ord":0,"own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","parent":"ytp1e5n","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","ord":1,"own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","parent":"ytp1e5n","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},{"align_key":"e2ffdc15a0aedd399bb1289258ce99f80f764cfb4124c273c5f5635884c9a05b","id":"exq1ter","kind":"paragraph","match_hash":"67882c3dc9b34613d96420fd3ca430b8be29013086f08f4ec203460f7b74ed04","node_hash":"9fe14a64167feee947551a33ebbe4f45ee8f242fa5f6d7f8b3c1ca6419efcb61","ord":2,"own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","parent":"b9wp3tt","text_hash":"67882c3dc9b34613d96420fd3ca430b8be29013086f08f4ec203460f7b74ed04"},{"align_key":"58ef15516c7e769fe65626153c05a0f99a693959c9efe141b1d3b05e5d45751e","content":[{"kind":"text","text":"A later paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","match_hash":"08cc4ab6f3ade7710e5f7fac5675ad9e4b6ec3eed4385dbddc01d3266b197860","node_hash":"7638ac33bece08d53c97170c50a2d42759fa8ae6970c27635f343b95c9190f7a","ord":0,"own_hash":"6681b0147e9aef501504638010d88c9d07a81fb66ead3e6bc21549a04d296bad","parent":"exq1ter","text_hash":"08cc4ab6f3ade7710e5f7fac5675ad9e4b6ec3eed4385dbddc01d3266b197860"},{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","ord":1,"own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","parent":"exq1ter","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","ord":3,"own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","parent":"b9wp3tt","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"t2ps2mp","kind":"table-head","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","ord":0,"own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","parent":"tb49qpc","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","id":"rr9rtf5","kind":"row","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"t2ps2mp","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","ord":0,"own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","parent":"rr9rtf5","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","ord":1,"own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","parent":"rr9rtf5","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","id":"dmsstkg","kind":"table-body","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","ord":1,"own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","parent":"tb49qpc","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","ord":0,"own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","parent":"dmsstkg","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","ord":0,"own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","parent":"r3e7hfs","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","ord":1,"own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","parent":"r3e7hfs","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"aw97y35","kind":"back","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","ord":1,"own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","parent":"s0fn2fj","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","id":"yd513mw","kind":"references","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","ord":0,"own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","parent":"aw97y35","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","ord":0,"own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","parent":"yd513mw","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"}],"record":{"after":"7638ac33bece08d53c97170c50a2d42759fa8ae6970c27635f343b95c9190f7a","at":"2026-10-11T12:00:00Z","author":{"model":{"name":"example-model","parameters":"998b5161e39e01c8bc43ef81ec89141e15b7ea53b2e936707920a6097dbcb2c5","processor":"local","prompt":"9cc338fba7c62db7266f530cb555a5ee36910d41a0120a3fe7fd7de1944d0931","provider":"Example Models (illustrative)","version":"2026-09","weights":"504b2d340045b92c22682b60020c21103aae7ff41172bb632fbe305eb4af9b5e"},"run":"illustrative-run-7"},"before":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","evidence":[{"by":"ana","kind":"person"}],"find":"second","format":"scienting-correction/1","id":"hzkw9vghv24az","index":1,"op":"replace","path":["s0fn2fj","b9wp3tt","exq1ter"],"reason":"Vector.","replace":"later","target":"j663d4h","touched":["j663d4h"]}},"id":"replace-by-model"} diff --git a/vectors/fingerprints.jsonl b/vectors/fingerprints.jsonl new file mode 100644 index 0000000..cd197d2 --- /dev/null +++ b/vectors/fingerprints.jsonl @@ -0,0 +1,6 @@ +{"id":"acs-download-1","page":{"images":[],"lines":[{"text":"Harmonic bond parameters for small organic molecules from a two-step fit"},{"text":"R. Hale and M. Osei"},{"text":"We fit harmonic bond constants for twelve bonds in two steps, first to a scan and then to vibrational frequencies."},{"text":"The two parameter sets agree to within 2% for every bond."},{"text":"Introduction"},{"text":"Harmonic bond terms remain the most common description of covalent stretching in classical force fields.1"},{"text":"The bond energy is given by $$E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2$$ where $K_r$ is the bond force constant and $r_\\mathrm{eq}$ the equilibrium bond length."},{"text":"Water, H$_2$O, served as the first test case, with a bending band near 1595 cm⁻¹.2"},{"text":"Values below 10−3 kcal mol⁻¹ were treated as zero."},{"text":"Table 1 lists the fitted constants for both parameter sets."},{"text":"CT–HC"},{"text":"340.0"},{"text":"1.090"},{"text":"338.7"},{"text":"1.0900"},{"text":"OW–HW"},{"text":"553.0"},{"text":"0.9572"},{"text":"548.1"},{"text":"0.9570"},{"box":[8,200,20,600],"text":"Downloaded via UNIVERSITY OF EXAMPLE on October 11, 2026 at 15:02:11 (UTC)."},{"box":[580,200,592,600],"text":"See https://pubs.acs.org/sharingguidelines for options on how to legitimately share published articles."}],"size":[612,792]},"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","removed":["downloaded-via","sharing-guidelines"],"rules":"scienting-stamps-1","text":"Harmonicbondparametersforsmallorganicmoleculesfromatwo-stepfitR.HaleandM.OseiWefitharmonicbondconstantsfortwelvebondsintwosteps,firsttoascanandthentovibrationalfrequencies.Thetwoparametersetsagreetowithin2%foreverybond.IntroductionHarmonicbondtermsremainthemostcommondescriptionofcovalentstretchinginclassicalforcefields.1Thebondenergyisgivenby$$E_{\\mathrm{bond}}=\\frac{1}{2}K_r(r-r_{\\mathrm{eq}})^2$$where$K_r$isthebondforceconstantand$r_\\mathrm{eq}$theequilibriumbondlength.Water,H$_2$O,servedasthefirsttestcase,withabendingbandnear1595cm^{−1}.2Valuesbelow10−3kcalmol^{−1}weretreatedaszero.Table1liststhefittedconstantsforbothparametersets.CT–HC340.01.090338.71.0900OW–HW553.00.9572548.10.9570"} +{"id":"acs-download-2","page":{"images":[],"lines":[{"text":"Harmonic bond parameters for small organic molecules from a two-step fit"},{"text":"R. Hale and M. Osei"},{"text":"We fit harmonic bond constants for twelve bonds in two steps, first to a scan and then to vibrational frequencies."},{"text":"The two parameter sets agree to within 2% for every bond."},{"text":"Introduction"},{"text":"Harmonic bond terms remain the most common description of covalent stretching in classical force fields.1"},{"text":"The bond energy is given by $$E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2$$ where $K_r$ is the bond force constant and $r_\\mathrm{eq}$ the equilibrium bond length."},{"text":"Water, H$_2$O, served as the first test case, with a bending band near 1595 cm⁻¹.2"},{"text":"Values below 10−3 kcal mol⁻¹ were treated as zero."},{"text":"Table 1 lists the fitted constants for both parameter sets."},{"text":"CT–HC"},{"text":"340.0"},{"text":"1.090"},{"text":"338.7"},{"text":"1.0900"},{"text":"OW–HW"},{"text":"553.0"},{"text":"0.9572"},{"text":"548.1"},{"text":"0.9570"},{"box":[8,210,20,590],"text":"Downloaded via EXAMPLE PHARMA INC on March 2, 2027 at 09:14:55 (UTC)."},{"box":[580,200,592,600],"text":"See https://pubs.acs.org/sharingguidelines for options on how to legitimately share published articles."}],"size":[612,792]},"page_fp":"6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","removed":["downloaded-via","sharing-guidelines"],"rules":"scienting-stamps-1","text":"Harmonicbondparametersforsmallorganicmoleculesfromatwo-stepfitR.HaleandM.OseiWefitharmonicbondconstantsfortwelvebondsintwosteps,firsttoascanandthentovibrationalfrequencies.Thetwoparametersetsagreetowithin2%foreverybond.IntroductionHarmonicbondtermsremainthemostcommondescriptionofcovalentstretchinginclassicalforcefields.1Thebondenergyisgivenby$$E_{\\mathrm{bond}}=\\frac{1}{2}K_r(r-r_{\\mathrm{eq}})^2$$where$K_r$isthebondforceconstantand$r_\\mathrm{eq}$theequilibriumbondlength.Water,H$_2$O,servedasthefirsttestcase,withabendingbandnear1595cm^{−1}.2Valuesbelow10−3kcalmol^{−1}weretreatedaszero.Table1liststhefittedconstantsforbothparametersets.CT–HC340.01.090338.71.0900OW–HW553.00.9572548.10.9570"} +{"id":"acs-changed-text","page":{"images":[],"lines":[{"text":"Harmonic bond parameters for small organic molecules from a two-step fit"},{"text":"R. Hale and M. Osei"},{"text":"We fit harmonic bond constants for twelve bonds in two steps, first to a scan and then to vibrational frequencies."},{"text":"The two parameter sets agree to within 2% for every bond."},{"text":"Introduction"},{"text":"Harmonic bond terms remain the most common description of covalent stretching in classical force fields.1"},{"text":"The bond energy is given by $$E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2$$ where $K_r$ is the bond force constant and $r_\\mathrm{eq}$ the equilibrium bond length."},{"text":"Water, H$_2$O, served as the first test case, with a bending band near 1594 cm⁻¹.2"},{"text":"Values below 10−3 kcal mol⁻¹ were treated as zero."},{"text":"Table 1 lists the fitted constants for both parameter sets."},{"text":"CT–HC"},{"text":"340.0"},{"text":"1.090"},{"text":"338.7"},{"text":"1.0900"},{"text":"OW–HW"},{"text":"553.0"},{"text":"0.9572"},{"text":"548.1"},{"text":"0.9570"},{"box":[8,200,20,600],"text":"Downloaded via UNIVERSITY OF EXAMPLE on October 11, 2026 at 15:02:11 (UTC)."},{"box":[580,200,592,600],"text":"See https://pubs.acs.org/sharingguidelines for options on how to legitimately share published articles."}],"size":[612,792]},"page_fp":"b545d28562fc1747d37b2418f4bb546581d1541218a377ff49864672d0f69d6e","removed":["downloaded-via","sharing-guidelines"],"rules":"scienting-stamps-1","text":"Harmonicbondparametersforsmallorganicmoleculesfromatwo-stepfitR.HaleandM.OseiWefitharmonicbondconstantsfortwelvebondsintwosteps,firsttoascanandthentovibrationalfrequencies.Thetwoparametersetsagreetowithin2%foreverybond.IntroductionHarmonicbondtermsremainthemostcommondescriptionofcovalentstretchinginclassicalforcefields.1Thebondenergyisgivenby$$E_{\\mathrm{bond}}=\\frac{1}{2}K_r(r-r_{\\mathrm{eq}})^2$$where$K_r$isthebondforceconstantand$r_\\mathrm{eq}$theequilibriumbondlength.Water,H$_2$O,servedasthefirsttestcase,withabendingbandnear1594cm^{−1}.2Valuesbelow10−3kcalmol^{−1}weretreatedaszero.Table1liststhefittedconstantsforbothparametersets.CT–HC340.01.090338.71.0900OW–HW553.00.9572548.10.9570"} +{"id":"wiley-download-1","page":{"images":["fc7fa8eee212bc9675823f9a9ae3c99da47b2f81b71db96eb6c870c4b2ddeece"],"lines":[{"text":"Results"},{"text":"The fitted slope is 0.42 ± 0.03 per kelvin."},{"box":[580,100,592,740],"text":"Downloaded from https://onlinelibrary.wiley.com/doi/10.5555/example.wiley by Example University, Wiley Online Library on [11/10/2026]. See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use."}],"size":[595.276,841.89]},"page_fp":"790d28cc2c1c24a1d3cae91490c15531ddeb0fc9a891cc68ea3b5118ad92e80a","removed":["downloaded-from-on"],"rules":"scienting-stamps-1","text":"ResultsThefittedslopeis0.42±0.03perkelvin."} +{"id":"wiley-download-2","page":{"images":["fc7fa8eee212bc9675823f9a9ae3c99da47b2f81b71db96eb6c870c4b2ddeece"],"lines":[{"text":"Results"},{"text":"The fitted slope is 0.42 ± 0.03 per kelvin."},{"box":[580,100,592,740],"text":"Downloaded from https://onlinelibrary.wiley.com/doi/10.5555/example.wiley by Example Pharma Inc, Wiley Online Library on [02/03/2027]."},{"box":[580,60,592,99],"text":"See the Terms and Conditions (https://onlinelibrary.wiley.com/terms-and-conditions) on Wiley Online Library for rules of use."}],"size":[595.276,841.89]},"page_fp":"790d28cc2c1c24a1d3cae91490c15531ddeb0fc9a891cc68ea3b5118ad92e80a","removed":["downloaded-from-on","terms-and-conditions"],"rules":"scienting-stamps-1","text":"ResultsThefittedslopeis0.42±0.03perkelvin."} +{"id":"scanned","page":{"images":["e7fe0677b342d86116a06d5d0865aef635be3fb52817be909d3c82258e31c8f1"],"lines":[],"size":[612.4,791.6]},"page_fp":"af1fbff58cac18341b82a5c0e3d48bb22663ef01ba183dbfc55a019d0a6e17b9","removed":[],"rules":"scienting-stamps-1","text":""} diff --git a/vectors/grading.jsonl b/vectors/grading.jsonl new file mode 100644 index 0000000..640a40a --- /dev/null +++ b/vectors/grading.jsonl @@ -0,0 +1,3 @@ +{"exercise":{"exercise":"anchor","format":"scienting-exercise/1","key":{"elements":[{"anchors":[{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","quote":{"exact":"310.0"},"rev":12,"store":"smithlab"}],"feedback":{"hit":"That is the cell.","miss":"Look in Table 1, row CT–CT."},"points":"1"}]},"prompt":"Find the table cell that gives the Set A bond constant for the CT–CT bond.","rule":{"match":"same-node"}},"expect":{"exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-grade/1","items":[{"element":"element:0","feedback":"That is the cell.","max":"1","points":"1"}],"max":"1","score":"1","submission":"kpjevbt3j6s3w"},"id":"anchor-hit","package":"fixtures/packages/hale2026harmonic-damb","submission":{"answers":{"anchors":[{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","quote":{"exact":"310.0"},"rev":12,"store":"smithlab"}]},"doc":"smithlab/hale2026harmonic-damb","exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-submission/1","id":"kpjevbt3j6s3w","rev":12,"student":"s-7k2m","submitted_at":"2026-10-20T10:00:00Z"}} +{"exercise":{"exercise":"anchor","format":"scienting-exercise/1","key":{"elements":[{"anchors":[{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","own_hash":"45bf6ab427d435f28b82cb2b64d93c502968921507fc9397abd5d5170731c6ab","quote":{"exact":"310.0"},"rev":12,"store":"smithlab"}],"feedback":{"hit":"That is the cell.","miss":"Look in Table 1, row CT–CT."},"points":"1"}]},"prompt":"Find the table cell that gives the Set A bond constant for the CT–CT bond.","rule":{"match":"same-node"}},"expect":{"exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-grade/1","items":[{"element":"element:0","feedback":"Look in Table 1, row CT–CT.","max":"1","points":"0"}],"max":"1","score":"0","submission":"ysw9hjztre498"},"id":"anchor-miss","package":"fixtures/packages/hale2026harmonic-damb","submission":{"answers":{"anchors":[{"context":{"column_path":["Set B","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"j6y45v6","node_hash":"00c4b92e220303ebc2bfb36aa557ac80ae4dba1675e9ed47adb82f6aeff10634","own_hash":"111d2b2cb30e3b04aff04b7de13a105a07a189d5ba97ae7d78eb7601ac99f9d9","quote":{"exact":"305.2"},"rev":12,"store":"smithlab"}]},"doc":"smithlab/hale2026harmonic-damb","exercise":"tag:scient.ing,2026:annotation:smithlab/whcypxav2cqbx","format":"scienting-submission/1","id":"ysw9hjztre498","rev":12,"student":"s-9q4p","submitted_at":"2026-10-20T10:00:00Z"}} +{"exercise":{"exercise":"check","format":"scienting-exercise/1","key":{"elements":[{"anchors":[{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"kea5026","node_hash":"b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33","own_hash":"d673d236c03d9583ecf6e01fa819765ec324dc684bd9bbc6967fa50f216e34d2","quote":{"exact":"the most common description","prefix":"Harmonic bond terms remain ","suffix":" of covalent stretching in class"},"rev":12,"span":[27,54],"store":"smithlab"}],"points":"1"}],"verdict":{"points":"1","value":"supports"}},"prompt":"Does the cited passage support the claim that harmonic terms are the most common choice?","rule":{"match":"overlap","min_overlap":"0.5"}},"expect":{"exercise":"tag:scient.ing,2026:annotation:smithlab/y7bd3he0jwjbx","format":"scienting-grade/1","items":[{"element":"verdict","feedback":"","max":"1","points":"1"},{"element":"element:0","feedback":"","max":"1","points":"1"}],"max":"2","score":"2","submission":"n7me2fmcw8ree"},"id":"check-overlap","package":"fixtures/packages/hale2026harmonic-damb","submission":{"answers":{"anchors":[{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"kea5026","node_hash":"b836d5872ca37471fa996be04c538254a8b1e37ca12e8f1b4a40837b503afa33","own_hash":"d673d236c03d9583ecf6e01fa819765ec324dc684bd9bbc6967fa50f216e34d2","quote":{"exact":"most common description of covalent","prefix":"Harmonic bond terms remain the ","suffix":" stretching in classical force f"},"rev":12,"span":[31,66],"store":"smithlab"}],"verdict":"supports"},"doc":"smithlab/hale2026harmonic-damb","exercise":"tag:scient.ing,2026:annotation:smithlab/y7bd3he0jwjbx","format":"scienting-submission/1","id":"n7me2fmcw8ree","rev":12,"student":"s-7k2m","submitted_at":"2026-10-20T10:05:00Z"}} diff --git a/vectors/hashes.jsonl b/vectors/hashes.jsonl new file mode 100644 index 0000000..c67013a --- /dev/null +++ b/vectors/hashes.jsonl @@ -0,0 +1 @@ +{"doc":"tiny2026tiny-j4qm","id":"tiny2026example","nodes":[{"id":"s0fn2fj","kind":"document","ord":0,"parent":null},{"attrs":{"level":1},"id":"b9wp3tt","kind":"section","label":"1","ord":0,"parent":"s0fn2fj"},{"id":"vet7k0e","kind":"heading","ord":0,"parent":"b9wp3tt"},{"content":[{"kind":"text","text":"Results"}],"fidelity":"F2","id":"em5pd9v","kind":"sentence","ord":0,"parent":"vet7k0e"},{"id":"ytp1e5n","kind":"paragraph","ord":1,"parent":"b9wp3tt"},{"content":[{"kind":"text","text":"The value is 42.0 at 300 K."}],"fidelity":"F2","id":"jvnys4s","kind":"sentence","ord":0,"parent":"ytp1e5n"},{"content":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}],"fidelity":"F2","id":"mzwwhxj","kind":"sentence","ord":1,"parent":"ytp1e5n"},{"id":"exq1ter","kind":"paragraph","ord":2,"parent":"b9wp3tt"},{"content":[{"kind":"text","text":"A second paragraph."}],"fidelity":"F2","id":"j663d4h","kind":"sentence","ord":0,"parent":"exq1ter"},{"content":[{"kind":"text","text":"It ends here."}],"fidelity":"F2","id":"rsw24qc","kind":"sentence","ord":1,"parent":"exq1ter"},{"attrs":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}]},"id":"tb49qpc","kind":"table","label":"Table 1","ord":3,"parent":"b9wp3tt"},{"id":"t2ps2mp","kind":"table-head","ord":0,"parent":"tb49qpc"},{"id":"rr9rtf5","kind":"row","ord":0,"parent":"t2ps2mp"},{"attrs":{"colspan":1,"column":"pj5sk05","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"x"}],"fidelity":"F1","id":"af5b51r","kind":"cell","ord":0,"parent":"rr9rtf5"},{"attrs":{"colspan":1,"column":"nymcs5q","role":"column-header","rowspan":1},"content":[{"kind":"text","text":"y"}],"fidelity":"F1","id":"ajqxkgh","kind":"cell","ord":1,"parent":"rr9rtf5"},{"id":"dmsstkg","kind":"table-body","ord":1,"parent":"tb49qpc"},{"attrs":{"header_path":["rdrqkv7"]},"id":"r3e7hfs","kind":"row","ord":0,"parent":"dmsstkg"},{"attrs":{"colspan":1,"column":"pj5sk05","role":"row-header","rowspan":1},"content":[{"kind":"text","text":"1"}],"fidelity":"F1","id":"rdrqkv7","kind":"cell","ord":0,"parent":"r3e7hfs"},{"attrs":{"colspan":1,"column":"nymcs5q","role":"data","rowspan":1},"content":[{"kind":"text","text":"2.5"}],"fidelity":"F1","id":"f463wj7","kind":"cell","ord":1,"parent":"r3e7hfs"},{"id":"aw97y35","kind":"back","ord":1,"parent":"s0fn2fj"},{"id":"yd513mw","kind":"references","ord":0,"parent":"aw97y35"},{"content":[{"kind":"text","text":"1. An Example, 2020."}],"fidelity":"F2","id":"r3e21zr","kind":"reference","label":"1","ord":0,"parent":"yd513mw"}],"own_content":{"af5b51r":{"colspan":1,"column":"pj5sk05","kind":"cell","role":"column-header","rowspan":1,"runs":[{"kind":"text","text":"x"}]},"ajqxkgh":{"colspan":1,"column":"nymcs5q","kind":"cell","role":"column-header","rowspan":1,"runs":[{"kind":"text","text":"y"}]},"aw97y35":{"kind":"back"},"b9wp3tt":{"heading":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","kind":"section","label":"1","level":1},"dmsstkg":{"kind":"table-body"},"em5pd9v":{"kind":"sentence","runs":[{"kind":"text","text":"Results"}]},"exq1ter":{"kind":"paragraph"},"f463wj7":{"colspan":1,"column":"nymcs5q","kind":"cell","role":"data","rowspan":1,"runs":[{"kind":"text","text":"2.5"}]},"j663d4h":{"kind":"sentence","runs":[{"kind":"text","text":"A second paragraph."}]},"jvnys4s":{"kind":"sentence","runs":[{"kind":"text","text":"The value is 42.0 at 300 K."}]},"mzwwhxj":{"kind":"sentence","runs":[{"kind":"text","text":"See "},{"kind":"xref","target":"tb49qpc","text":"Table 1"},{"kind":"text","text":" and the note."},{"kind":"cite","refs":["r3e21zr"],"text":"1"}]},"r3e21zr":{"kind":"reference","label":"1","runs":[{"kind":"text","text":"1. An Example, 2020."}]},"r3e7hfs":{"kind":"row"},"rdrqkv7":{"colspan":1,"column":"pj5sk05","kind":"cell","role":"row-header","rowspan":1,"runs":[{"kind":"text","text":"1"}]},"rr9rtf5":{"kind":"row"},"rsw24qc":{"kind":"sentence","runs":[{"kind":"text","text":"It ends here."}]},"s0fn2fj":{"kind":"document"},"t2ps2mp":{"kind":"table-head"},"tb49qpc":{"columns":[{"header_path":["af5b51r"],"id":"pj5sk05"},{"header_path":["ajqxkgh"],"id":"nymcs5q"}],"kind":"table","label":"Table 1"},"vet7k0e":{"kind":"heading"},"yd513mw":{"kind":"references"},"ytp1e5n":{"kind":"paragraph"}},"values":{"af5b51r":{"align_key":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","match_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","node_hash":"59d1c20766a77bacde2aae80a134c7156fbcc708c140a3bb2d2a67f78bd9c6f5","own_hash":"c68933b07bc7c5b806892ae36b3e4c3205a0a2066fd6f8255578f7d1ca86dc10","text_hash":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"},"ajqxkgh":{"align_key":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","match_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa","node_hash":"838e3fba38f0797d40522b7063cb5c2962e32a019c09c19f09849ced73079a87","own_hash":"28df42bf1dcd44b053275ed014bd1599914f17adabc0c7fdb3e4247dc648ac49","text_hash":"a1fce4363854ff888cff4b8e7875d600c2682390412a8cf79b37d0b11148b0fa"},"aw97y35":{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"fcb8027f7c89115f048b9c5d6770847248f4e4fbc61cbc8ea0b04079b4d58350","own_hash":"bbb972bdc024231b505f4d8ce5e711fbb75c8b5ffd1b5d42ee3fb8586b85f867","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},"b9wp3tt":{"align_key":"caf6aee3882b3890996037e35d0ffdfe30b5e66653d45321d7ea0fa9135f1ee9","match_hash":"5a96c01f314c4d8a22fd5e105bebef45df4301886cccbc2538ecefddfcb1d405","node_hash":"ea9a1409bbf0f0f7bd8d508bfdbbf7d14a22ab1e3da011eafbfcd4e14ae7e4fd","own_hash":"65da097b48f8237e8d171bfbd0053ff0e3795c0532d5522d23a92b53430956f4","text_hash":"7a97628fe9643c0fca3614a077e2e631c3fee81d3733ba1564292df65a294573"},"dmsstkg":{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"baf17577660aa6f0ba9c8703d30816d77cfce7dbf0ea3257ed830fa9ab94ce9d","own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},"em5pd9v":{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"293fc03ff4e39d7532467e4417ffcdb15f470f0bd3658dc1c021645ad53c9bef","own_hash":"c55f401232b19ff1133d77eac6c72868975064f177fc2d31ab8a181303c30599","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},"exq1ter":{"align_key":"282eea00b316a6950fb7179f6289a8b98359019e11cb23a3ff426cdecad90165","match_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1","node_hash":"062dd26bfb226ca9811d0dfb013df211cb201dfe7b4b25f9aba000f3212298d5","own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","text_hash":"da88f35d24faf0099610c720953c4919647a5dfb9003889a15c464cd9c540fb1"},"f463wj7":{"align_key":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","match_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61","node_hash":"f1cd6d5339c84d5c36f8e1ea484a8d837f3200f05d1b106f6119dfa30d846bfd","own_hash":"088eff622eb3086d68c4433cf5e1783dc9f2a6724c3536c31ec0bf80b5f89db5","text_hash":"b8736b999909049671d0ea075a42b308a5fbe2df1854899123fe09eb0ee9de61"},"j663d4h":{"align_key":"b8074a8bc013aa007023c4cce7334f1e1f22384d57a526ca22fd2f5589d5ab17","match_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e","node_hash":"443539440dca73149ca75276492334ce9a5a6c50070137e8dc7bf414b75a27ab","own_hash":"acee4b6b1399bfde1dc67dea8d8c86b0db961d2af516ae4aaee26f294261456f","text_hash":"2e8313b033de5e17878ae778d6293bbd6e197a072f36acf7fe0840a690a7f31e"},"jvnys4s":{"align_key":"8f21603c39df123eb8680362184274aac9bdf1dbd485b3bba230960179071c95","match_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3","node_hash":"f5761f338b2878dff39a6ee724a75b13626dd625a0df96cf1cc6f9e8258cb7cc","own_hash":"7f0b9190d076cf01b51a8be863a51e9a8eeaab5d3ec8656202ff4d41578d4d82","text_hash":"3bcf9fa8412dca28be91d6423460233ddedd7add6c324d8a0f2b26038567d3d3"},"mzwwhxj":{"align_key":"8e7fe271cd1bab88d86c8900fe3ffae0ce95c55af6659df1fca278d359296e2d","match_hash":"9894a48790a8561966e68672fa13da20541d25a5178653720648f62cbc9ad36b","node_hash":"8f3e5338ba3c97efca4cef5c60d849757aed6334ee27ab807fa71d969089e46e","own_hash":"02ed6d50b8ac607b59e3f7b5116ee6143ed7e69af25b19c4037aa799bc330a88","text_hash":"5b1de19c9eb1399e54bde7e96f051cac8b337be1f307fac320292b8db7e39da7"},"r3e21zr":{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"71b1af6dd6a56f24cb3b338e0fe99df06b9154ecdf4b391b00b7a7e61e23a8ed","own_hash":"f7c9bbc8c7456e6dc435feeaaa02cbfdbe487523b020105793fb11b91d0894f5","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},"r3e7hfs":{"align_key":"b902cc4550838229a710bfec4c38cbc7eb11082367a409df9135e7f007a96bda","match_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738","node_hash":"97a1f5b27bbfe8c9d2cec7212b519b4993506fc8080be3eff02f3aa31515a19d","own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","text_hash":"24cb52bc2dd0b9ddd4650c011d76b585e76c4d4ecae8cf220c7600efb808d738"},"rdrqkv7":{"align_key":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","match_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","node_hash":"87da3bd568286f3d0578d8a813496d15faafb62f4db44b07aa1c29e52cda34df","own_hash":"fb474321001657b59bccd3cae0987c544a4ef9a27214626d77695f4db237aa93","text_hash":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"},"rr9rtf5":{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"8bd1fa377ec390fdc36e17baa8c3a39d2df7ef2a53cd0c0dc745ae40e98f99f8","own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},"rsw24qc":{"align_key":"437c101749b0481e615fc7eed8dcacb536b65400c7e0695ad4cbb2bf2dae488c","match_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882","node_hash":"caeb3ae57d0821b8ac961c9507debbcda2b118b16cdc010b83a143a782058d57","own_hash":"705f77e8520c8c5ce3a7a495a20d8a9c55baa9801e49a55c341f5de79eeede75","text_hash":"2888dbfa0c08fd65c58c923b920860c76e13913d9fa93b03eccbbf7bdf53b882"},"s0fn2fj":{"align_key":"b3108c22ec836d883e5116f7ed8546fa75390eb4aa960d78f2936115f69b6826","match_hash":"b6a4e12f700a6214bf02c9a437559e82fccdbecea7b575fa438a7d2e8c33071a","node_hash":"a05328e6d13edba652599aceb58c018dbccf54abd1f878c9f61623017960e1fe","own_hash":"34444fe0e6bdbf3927a579fe3286859d204ea0882a381b7769ffd4905551d24f","text_hash":"bd2abc746d51cf52d57a18632383245d585e29e265426967894eed99bc937561"},"t2ps2mp":{"align_key":"769a4e6d0003189c7e96c5d9b7e810a0d11c3a12832527ec94b0f86d277f51ca","match_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19","node_hash":"6d8056adfb50dc0b65a2a65b47eccc5f47d5482a8dfbefa0d8a06f6641a4be3a","own_hash":"c5749bee3a4b981fb79cf6db125ebb416dce5a83613a00feecd9d4cf75df9bb4","text_hash":"887fcea6a80333c6c02ae7e79735f0edad8d811f0b61431495f796f4bf6a7c19"},"tb49qpc":{"align_key":"cb0107aa0d562e8bd1188c33dc1ef5a1d07808e51edeabaa87465556d11b6ec8","match_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72","node_hash":"154c910857f33c152fdc78e42582510327055e62da9a25ab10c3891eeaf69627","own_hash":"fb4cc66080def0b42a06f7aa566a24957c7345c77b8d873ca5c790704a890f47","text_hash":"1951e0b61441d7b817b4967b36eee007f8e7525ac75fd359437eddb871e59f72"},"vet7k0e":{"align_key":"c099142bc3186ded72786ba27e9ea6d2da240fb9fd3fe79b479ecf8e734b2850","match_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd","node_hash":"a3c82ab1e44bf4cffa1a59507f8bddc39a1ad191321ee803d0d60d96609a44c7","own_hash":"e813ff86a8920cef741e548eb5df545774b520d2fadbdda6e2b872a6729b9d26","text_hash":"219c4a6c86a716e99d5dc9611b61e584deb11b57e972d87d4b773387ebc3cadd"},"yd513mw":{"align_key":"b35d81b0ff35d6d05ad2c187a289d3017896427dfd8bb98160bc806ac0ec32f7","match_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e","node_hash":"8b8a9000e984c3efeb27fc40c8fbadd7349dd64860aa276dcd2a25a57ce52e87","own_hash":"2a5302e2041d0e59458fea212dd51b89299901318bfceeeff227c1a07d3f5d1a","text_hash":"9a2d5d28ee47736a00d074e066bb944154f95a192360c8c04226c3d12a4f7d1e"},"ytp1e5n":{"align_key":"610c235321e38145abff21e31eaab303d85a6ce0d1b9340a599dc821a04922f6","match_hash":"bcb4902ec69f2a7a724384f561ee9aa0e214c824c5882c1ad92777bee680aad4","node_hash":"7667a3a4bc2e8fec1dc7af53e19c414952f9ce926b1e37e8d9adca66dd8f8d1d","own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","text_hash":"f589ee914c46c4aea7ce2de49d925c433c914121f576b81a3eab692f17f179a3"}}} diff --git a/vectors/ids.jsonl b/vectors/ids.jsonl new file mode 100644 index 0000000..aa3b497 --- /dev/null +++ b/vectors/ids.jsonl @@ -0,0 +1,8 @@ +{"doc":"cornell1995second","id":"mint-cornell1995second-sentence-0","kind":"sentence","node_id":"m0666ac","occurrence":0,"payload":"[\"scienting-id/1\",\"cornell1995second\",\"sentence\",\"92cc199c38785d890c7e284dbe881d529d25650998e4178eb0515ac930140eff\",0]","sha256":"8e018c65322796ed82da86ab61b447d459e05eff453a01036b9b2551ad96e62d","text_hash":"92cc199c38785d890c7e284dbe881d529d25650998e4178eb0515ac930140eff"} +{"doc":"cornell1995second","id":"mint-cornell1995second-sentence-1","kind":"sentence","node_id":"ahp2fgc","occurrence":1,"payload":"[\"scienting-id/1\",\"cornell1995second\",\"sentence\",\"92cc199c38785d890c7e284dbe881d529d25650998e4178eb0515ac930140eff\",1]","sha256":"008d84f8315477ba07b5562fead3fc98f0920b2767a57841c88f518d18514ed1","text_hash":"92cc199c38785d890c7e284dbe881d529d25650998e4178eb0515ac930140eff"} +{"doc":"cornell1995second.si","id":"mint-cornell1995second.si-sentence-0","kind":"sentence","node_id":"za1xybq","occurrence":0,"payload":"[\"scienting-id/1\",\"cornell1995second.si\",\"sentence\",\"92cc199c38785d890c7e284dbe881d529d25650998e4178eb0515ac930140eff\",0]","sha256":"2b507be5de00943482fe0c669e67544bdb81816906e91929be17df5a7cbf9ead","text_hash":"92cc199c38785d890c7e284dbe881d529d25650998e4178eb0515ac930140eff"} +{"doc":"hale2026harmonic-damb","id":"mint-hale2026harmonic-damb-cell-0","kind":"cell","node_id":"k3g2dr6","occurrence":0,"payload":"[\"scienting-id/1\",\"hale2026harmonic-damb\",\"cell\",\"b478fdfee29a549693a103681b3ad91c628d0f16ad0a7b2c5b089fe8ecd1f6ca\",0]","sha256":"cf1c04dc1b3d561b469f7daf6182cd52713716605421927155a19c9dab31c4f4","text_hash":"b478fdfee29a549693a103681b3ad91c628d0f16ad0a7b2c5b089fe8ecd1f6ca"} +{"doc":"hale2026harmonic-damb","id":"mint-hale2026harmonic-damb-column-0","kind":"column","node_id":"wdtrcqt","occurrence":0,"payload":"[\"scienting-id/1\",\"hale2026harmonic-damb\",\"column\",\"ff13bf8f571a0a91afeb93bca4cecccdd5d069b06cab8264d8318183bb572c24\",0]","sha256":"ee6eb0cbea0d30f6aa52f684947bb3346f67c91c2c0276a8d0a08f20aa23a7e3","text_hash":"ff13bf8f571a0a91afeb93bca4cecccdd5d069b06cab8264d8318183bb572c24"} +{"digest":"0000000000000000000000000000000000000000000000000000000000000000","id":"letter-first-00000000","node_id":"a000000","record_id":"a000000000000"} +{"digest":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","id":"letter-first-ffffffff","node_id":"qzzzzzz","record_id":"qzzzzzzzzzzzz"} +{"digest":"2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881","id":"letter-first-2d711642","node_id":"be4b45d","record_id":"be4b45ds6p120"} diff --git a/vectors/keyed.jsonl b/vectors/keyed.jsonl new file mode 100644 index 0000000..cb1ab04 --- /dev/null +++ b/vectors/keyed.jsonl @@ -0,0 +1,5 @@ +{"id":"team-key","key":"18bbe0daeb812b646577a77fe05e8a8ff77695b8a5121ab859e051812cafb66d","key_id":"dc3a5e64b55a972b","secret":"30fe6ec81905c8e0412719dd02bebe483c72ecd867332c76a35c67654ad5db18"} +{"id":"team-hmac-text","key":"18bbe0daeb812b646577a77fe05e8a8ff77695b8a5121ab859e051812cafb66d","text":"310.0","text_hash_keyed":"9df4869eb9769862199036065318395ff4a2b2bc6fb1ff9592bea75fce1fe05f","text_hash_plain":"b478fdfee29a549693a103681b3ad91c628d0f16ad0a7b2c5b089fe8ecd1f6ca"} +{"id":"page-hashes","page_fps":["6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60"],"page_hashes":["9dd865c7a19b44dc97a5d236859ed79174b25b72a5781d8df4f091d096de8908","1feb6882031349ca5eee822557bab0b6b0436a2d132ae8ca03babac2ff1948b8"]} +{"context":"layer:smithlab/kp4m2x7q","id":"page-key","key":"9261e87d2bc1d4b20467346c447b3966c90497d846b04d3ce35fd4155719e925","page_fps":["6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","128d5f76c2c78ee9410c2ab4dda8abaee279db0caeec8a1cc019c3b1bd04ba60"],"quote":"310.0","quote_mac":"0d8d4fcd55f1a4cfd7f254d597b7a5777b8865eb371283c03527ac8195ebb5ac"} +{"guess":"310.0","guess_sha256":"b478fdfee29a549693a103681b3ad91c628d0f16ad0a7b2c5b089fe8ecd1f6ca","id":"non-holder","note":"Without the pages, a guess hashes to the plain value, which the export never carries; with one page changed, the key differs.","quote_mac":"0d8d4fcd55f1a4cfd7f254d597b7a5777b8865eb371283c03527ac8195ebb5ac","wrong_key":"759a346f4816f2f5777b4122bd65134d0abcc263eab24298040644a12b6491b2","wrong_page_fps":["6272e6f3f4c1372f81ebcd20b813b836c62a1d683151cf135fc13900136213af","59705a341da66488fe33522f8aa4d5f4fbb7438c790804a3dc35890ac46e3515"]} diff --git a/vectors/keys.jsonl b/vectors/keys.jsonl new file mode 100644 index 0000000..ea05614 --- /dev/null +++ b/vectors/keys.jsonl @@ -0,0 +1,22 @@ +{"id":"doi","identity":"doi:10.48550/arxiv.1706.03762","key":"vaswani2017attention-a241","meta":{"author":[{"family":"Vaswani","given":"Ashish"}],"issued":{"date-parts":[[2017]]},"title":"Attention is all you need"},"payload":"scienting-key/1:doi:10.48550/arxiv.1706.03762","same_as":["doi:10.48550/arXiv.1706.03762"],"scholar":"vaswani2017attention","sha256":"50881f3522a3163b00faf40f757a0e12f03e5888be4eb39223deecb40e97e7a2","suffix":"a241","suffix_8":"a241yd92"} +{"id":"openalex","identity":"openalex:W2963403868","key":"vaswani2017attention-665j","meta":{"author":[{"family":"Vaswani","given":"Ashish"}],"issued":{"date-parts":[[2017]]},"title":"Attention is all you need"},"payload":"scienting-key/1:openalex:W2963403868","same_as":["openalex:W2963403868"],"scholar":"vaswani2017attention","sha256":"318b28d01661b2d1fad44caddb03a5663542fcc96f63abca1f74189c6e940e6d","suffix":"665j","suffix_8":"665jhm0p"} +{"id":"doi-before-arxiv","identity":"doi:10.48550/arxiv.1706.03762","key":"vaswani2017attention-a241","meta":{"author":[{"family":"Vaswani","given":"Ashish"}],"issued":{"date-parts":[[2017]]},"title":"Attention is all you need"},"payload":"scienting-key/1:doi:10.48550/arxiv.1706.03762","same_as":["arxiv:1706.03762","doi:10.48550/arXiv.1706.03762"],"scholar":"vaswani2017attention","sha256":"50881f3522a3163b00faf40f757a0e12f03e5888be4eb39223deecb40e97e7a2","suffix":"a241","suffix_8":"a241yd92"} +{"id":"arxiv-only","identity":"arxiv:1706.03762","key":"vaswani2017attention-0gsr","meta":{"author":[{"family":"Vaswani","given":"Ashish"}],"issued":{"date-parts":[[2017]]},"title":"Attention is all you need"},"payload":"scienting-key/1:arxiv:1706.03762","same_as":["arxiv:1706.03762"],"scholar":"vaswani2017attention","sha256":"04338a071acb344bf1d2a587d80ebb407cb00d0428a68fd09c4c2dfb773d86ca","suffix":"0gsr","suffix_8":"0gsrm1rt"} +{"id":"url-is-not-an-identity","identity":"meta:attention is all you need|2017|vaswani","key":"vaswani2017attention-cjj0","meta":{"author":[{"family":"Vaswani","given":"Ashish"}],"issued":{"date-parts":[[2017]]},"title":"Attention is all you need"},"payload":"scienting-key/1:meta:attention is all you need|2017|vaswani","same_as":["url:https://example.org/paper"],"scholar":"vaswani2017attention","sha256":"64a4022cc33a7090fedb0c398c9b5ea29d49b179930cbbe10fbf66848dc400f7","suffix":"cjj0","suffix_8":"cjj04b63"} +{"id":"meta","identity":"meta:on the origin of species|1859|darwin","key":"darwin1859origin-rtee","meta":{"author":[{"family":"Darwin","given":"Charles"}],"issued":{"date-parts":[[1859]]},"title":"On the Origin of Species"},"payload":"scienting-key/1:meta:on the origin of species|1859|darwin","same_as":[],"scholar":"darwin1859origin","sha256":"c69cea2092bd27e2afb1ddb21042cef751af5351792c480f06e408149bbf6d29","suffix":"rtee","suffix_8":"rteem84j"} +{"id":"doi-case","identity":"doi:10.1109/cvpr.2016.90","key":"he2016deep-mayp","meta":{"author":[{"family":"He","given":"Kaiming"}],"issued":{"date-parts":[[2016]]},"title":"Deep Residual Learning for Image Recognition"},"payload":"scienting-key/1:doi:10.1109/cvpr.2016.90","same_as":["doi:10.1109/CVPR.2016.90"],"scholar":"he2016deep","sha256":"a2bd628f5f0e51977bf7995d5ee5111efee52d2f2f1aa0a0069b1e5bee49e54e","suffix":"mayp","suffix_8":"mayp53tz"} +{"id":"accents","identity":"meta:a new method|2001|muller","key":"muller2001new-zbs5","meta":{"author":[{"literal":"Müller, Jürgen"}],"issued":{"date-parts":[[2001]]},"title":"A new method"},"payload":"scienting-key/1:meta:a new method|2001|muller","same_as":[],"scholar":"muller2001new","sha256":"faf25f3aa55a6fb452901708bb5dc98937ba6b4e1227a7bac04b23fa5199f250","suffix":"zbs5","suffix_8":"zbs5yen5"} +{"id":"apostrophe","identity":"meta:dont stop|2020|obrien","key":"obrien2020dont-r6wf","meta":{"author":[{"literal":"Conan O'Brien"}],"issued":{"date-parts":[[2020]]},"title":"Don't stop"},"payload":"scienting-key/1:meta:dont stop|2020|obrien","same_as":[],"scholar":"obrien2020dont","sha256":"c1b8f70a3f82497c6cd08b13f3e6a28644aa46498d81c1dc805c4d6b6d82a016","suffix":"r6wf","suffix_8":"r6wfe2hz"} +{"id":"name-suffix","identity":"meta:3d printing of bone|2015|smith","key":"smith20153d-t295","meta":{"author":[{"literal":"A. Smith Jr."}],"issued":{"date-parts":[[2015]]},"title":"3D printing of bone"},"payload":"scienting-key/1:meta:3d printing of bone|2015|smith","same_as":[],"scholar":"smith20153d","sha256":"d0925b487a841a22b53b9af3dc62286c02a8128aa4a05e25f3e0e9358da02713","suffix":"t295","suffix_8":"t295pj3t"} +{"id":"only-stop-words","identity":"meta:the of a|2019|lee","key":"lee2019-y540","meta":{"author":[{"family":"Lee","given":"Jo"}],"issued":{"date-parts":[[2019]]},"title":"The of a"},"payload":"scienting-key/1:meta:the of a|2019|lee","same_as":[],"scholar":"lee2019","sha256":"f14807d773f8d38a4c2265aeb2339d972ff13636bfef4a4cd297f15c9ce27bb5","suffix":"y540","suffix_8":"y540fnvk"} +{"id":"no-year","identity":"meta:untitled||lee","key":"leeuntitled-k71m","meta":{"author":[{"family":"Lee"}],"title":"Untitled"},"payload":"scienting-key/1:meta:untitled||lee","same_as":[],"scholar":"leeuntitled","sha256":"99c3443c5c433c6b7f735d2ace90771611709e112854253be6c5050e351e3c13","suffix":"k71m","suffix_8":"k71m8f2w"} +{"id":"no-author","identity":"meta:fluids|2020|anon","key":"anon2020fluids-5mhd","meta":{"issued":{"date-parts":[[2020]]},"title":"Fluids"},"payload":"scienting-key/1:meta:fluids|2020|anon","same_as":[],"scholar":"anon2020fluids","sha256":"2d22d0eb26220e2e143afb5c8d7cdd7b9cc13bd80c23141286ce5f95d3a27374","suffix":"5mhd","suffix_8":"5mhd1ts6"} +{"id":"non-latin-author","identity":"meta:fluids|2020|anon","key":"anon2020fluids-5mhd","meta":{"author":[{"family":"张伟"}],"issued":{"date-parts":[[2020]]},"title":"Fluids"},"payload":"scienting-key/1:meta:fluids|2020|anon","same_as":[],"scholar":"anon2020fluids","sha256":"2d22d0eb26220e2e143afb5c8d7cdd7b9cc13bd80c23141286ce5f95d3a27374","suffix":"5mhd","suffix_8":"5mhd1ts6"} +{"id":"hale","identity":"doi:10.5555/example.hale.2026","key":"hale2026harmonic-damb","meta":{"DOI":"10.5555/example.hale.2026","author":[{"family":"Hale","given":"R."},{"family":"Osei","given":"M."}],"container-title":"Journal of Example Chemistry","issued":{"date-parts":[[2026,3,2]]},"page":"101-109","title":"Harmonic bond parameters for small organic molecules from a two-step fit","type":"article-journal","volume":"14"},"payload":"scienting-key/1:doi:10.5555/example.hale.2026","same_as":["doi:10.5555/example.hale.2026"],"scholar":"hale2026harmonic","sha256":"6aa8b08a7789e518050223ace630d6bc1657c4ad79e39bab14c2d3ae295add5b","suffix":"damb","suffix_8":"damb12kq"} +{"document_key":"hale2026harmonic-damb","id":"document-version-of-record","version":{"type":"version-of-record"},"work_key":"hale2026harmonic-damb"} +{"document_key":"hale2026harmonic-damb.si","id":"document-supplement","version":{"type":"supplement"},"work_key":"hale2026harmonic-damb"} +{"document_key":"hale2026harmonic-damb.v2","id":"document-preprint-v2","version":{"seq":2,"type":"preprint"},"work_key":"hale2026harmonic-damb"} +{"document_key":"hale2026harmonic-damb.v3","id":"document-draft-v3","version":{"seq":3,"type":"draft"},"work_key":"hale2026harmonic-damb"} +{"document_key":"hale2026harmonic-damb.erratum","id":"document-erratum","version":{"type":"erratum"},"work_key":"hale2026harmonic-damb"} +{"document_key":"hale2026harmonic-damb.accepted","id":"document-accepted-no-seq","version":{"type":"accepted"},"work_key":"hale2026harmonic-damb"} +{"id":"collision","key":"vaswani2017attention-a241yd","meta":{"author":[{"family":"Vaswani","given":"Ashish"}],"issued":{"date-parts":[[2017]]},"title":"Attention is all you need"},"same_as":["doi:10.48550/arXiv.1706.03762"],"taken":["vaswani2017attention-a241"]} diff --git a/vectors/merkle.jsonl b/vectors/merkle.jsonl new file mode 100644 index 0000000..6dbbc3d --- /dev/null +++ b/vectors/merkle.jsonl @@ -0,0 +1,6 @@ +{"id":"items-1","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"]],"root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d"} +{"id":"items-2","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"]],"root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"} +{"id":"items-3","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68"} +{"id":"items-4","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"} +{"id":"items-5","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978"} +{"id":"items-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} diff --git a/vectors/normalize.jsonl b/vectors/normalize.jsonl new file mode 100644 index 0000000..606b28a --- /dev/null +++ b/vectors/normalize.jsonl @@ -0,0 +1,9 @@ +{"id":"nfc","input":"café","output":"café","sha256":"850f7dc43910ff890f8879c0ed26fe697c93a067ad93a7d50f466a7028a9bf4e"} +{"id":"collapse","input":"a \t\n b","output":"a b","sha256":"c8687a08aa5d6ed2044328fa6a697ab8e96dc34291e8c2034ae8c38e6fcc6d65"} +{"id":"trim","input":"  a b  ","output":"a b","sha256":"c8687a08aa5d6ed2044328fa6a697ab8e96dc34291e8c2034ae8c38e6fcc6d65"} +{"id":"angstrom-sign","input":"1.5 Å","output":"1.5 Å","sha256":"3560124dc46b97829d3cac905d18ff5abd7a9f75c7febff30b39b070a737ea09"} +{"id":"nbsp-thin","input":"300 K and 10 mol","output":"300 K and 10 mol","sha256":"2a620a3e13ea0187f32808491d258d53e161af8db36c614e91df9e625bad7440"} +{"id":"zero-width-kept","input":"a​b","output":"a​b","sha256":"8df62aef5f92e4c30c0c938497f55f60078c361a476e7e0448485194ad79f884"} +{"id":"ligature-kept","input":"fit","output":"fit","sha256":"b4ad6ce484479733a24952a73897a9ab4a329b663b6b279162471c3834dbd266"} +{"id":"micro-kept","input":"5 µm","output":"5 µm","sha256":"92794248cd1afe73490b3cb49f88608b3e92c920c70e9816b33987cb54b1f8ba"} +{"id":"line-separator","input":"one
two","output":"one two","sha256":"8ab63e29a4ba14e4e1688f9c15e5af90895421358c945b0431f85d66977bd3d2"} diff --git a/vectors/notation.jsonl b/vectors/notation.jsonl new file mode 100644 index 0000000..35b3f06 --- /dev/null +++ b/vectors/notation.jsonl @@ -0,0 +1,42 @@ +{"canonical":"H_{2}O","id":"tex:H_2O","notation":"tex","source":"H_2O"} +{"canonical":"_{2}","id":"tex:_2","notation":"tex","source":"_2"} +{"canonical":"H_{2}O","id":"tex:\\mathrm{H}_{2}\\mathrm{O}","notation":"tex","source":"\\mathrm{H}_{2}\\mathrm{O}"} +{"canonical":"H_{2}O","id":"typst:H_2 O","notation":"typst","source":"H_2 O"} +{"canonical":"H_{2}O","id":"typst:upright(H)_2 upright(O)","notation":"typst","source":"upright(H)_2 upright(O)"} +{"canonical":"cm^{−1}","id":"tex:\\mathrm{cm}^{-1}","notation":"tex","source":"\\mathrm{cm}^{-1}"} +{"canonical":"cm^{−1}","id":"typst:\"cm\"^(-1)","notation":"typst","source":"\"cm\"^(-1)"} +{"canonical":"10^{−3}","id":"tex:10^{-3}","notation":"tex","source":"10^{-3}"} +{"canonical":"10^{−3}","id":"typst:10^(-3)","notation":"typst","source":"10^(-3)"} +{"canonical":"K_{r}","id":"tex:K_r","notation":"tex","source":"K_r"} +{"canonical":"K_{r}","id":"tex:K_{\\mathrm{r}}","notation":"tex","source":"K_{\\mathrm{r}}"} +{"canonical":"K_{r}","id":"typst:K_r","notation":"typst","source":"K_r"} +{"canonical":"α_{i}","id":"tex:\\alpha_i","notation":"tex","source":"\\alpha_i"} +{"canonical":"α_{i}","id":"tex:\\alpha_{i}","notation":"tex","source":"\\alpha_{i}"} +{"canonical":"x′_{1}","id":"tex:x'_1","notation":"tex","source":"x'_1"} +{"canonical":"x′","id":"tex:x^{\\prime}","notation":"tex","source":"x^{\\prime}"} +{"canonical":"T=300K","id":"tex:T = 300\\,\\mathrm{K}","notation":"tex","source":"T = 300\\,\\mathrm{K}"} +{"canonical":"−1.5","id":"tex:-1.5","notation":"tex","source":"-1.5"} +{"canonical":"ϵ","id":"tex:\\epsilon","notation":"tex","source":"\\epsilon"} +{"canonical":"ϵ","id":"typst:epsilon.alt","notation":"typst","source":"epsilon.alt"} +{"canonical":"a⋅b","id":"tex:a \\cdot b","notation":"tex","source":"a \\cdot b"} +{"canonical":"a⋅b","id":"typst:a dot b","notation":"typst","source":"a dot b"} +{"canonical":"a×b±c","id":"tex:a \\times b \\pm c","notation":"tex","source":"a \\times b \\pm c"} +{"canonical":"(x)^{2}","id":"tex:\\left(x\\right)^2","notation":"tex","source":"\\left(x\\right)^2"} +{"canonical":"(a+b)^{2}","id":"typst:(a+b)^2","notation":"typst","source":"(a+b)^2"} +{"canonical":null,"id":"tex:\\frac{a}{b}","notation":"tex","source":"\\frac{a}{b}"} +{"canonical":null,"id":"typst:a/b","notation":"typst","source":"a/b"} +{"canonical":null,"id":"tex:\\sqrt{2}","notation":"tex","source":"\\sqrt{2}"} +{"canonical":null,"id":"tex:\\mathbf{F}","notation":"tex","source":"\\mathbf{F}"} +{"canonical":null,"id":"tex:{ab}_2","notation":"tex","source":"{ab}_2"} +{"canonical":null,"id":"tex:x_1_2","notation":"tex","source":"x_1_2"} +{"canonical":null,"id":"tex:\\Delta G^\\circ","notation":"tex","source":"\\Delta G^\\circ"} +{"canonical":null,"id":"tex:E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2","notation":"tex","source":"E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2"} +{"canonical":"E=K_{r}(r−r_{eq})^{2}","id":"typst:E = K_r (r - r_\"eq\")^2","notation":"typst","source":"E = K_r (r - r_\"eq\")^2"} +{"canonical":"^{14}C","id":"tex:{}^{14}C","notation":"tex","source":"{}^{14}C"} +{"canonical":"x^{2}","id":"tex:x{}^2","notation":"tex","source":"x{}^2"} +{"canonical":"_{2}","id":"tex:{}_2","notation":"tex","source":"{}_2"} +{"canonical":null,"id":"tex:\\left)x\\right(","notation":"tex","source":"\\left)x\\right("} +{"canonical":null,"id":"tex:A","notation":"tex","source":"A"} +{"canonical":null,"id":"tex:ʰ","notation":"tex","source":"ʰ"} +{"canonical":null,"id":"tex:Ϣ","notation":"tex","source":"Ϣ"} +{"canonical":"ἀω","id":"tex:ἀω","notation":"tex","source":"ἀω"} diff --git a/vectors/offsets.jsonl b/vectors/offsets.jsonl new file mode 100644 index 0000000..db09f44 --- /dev/null +++ b/vectors/offsets.jsonl @@ -0,0 +1,2 @@ +{"code_points":24,"exact":"$_2$O.","id":"bmp","plain":"A sentence about H$_2$O.","runs":[{"kind":"text","text":"A sentence about H"},{"kind":"math","notation":"tex","source":"_2"},{"kind":"text","text":"O."}],"span":[18,24],"utf16_span":[18,24],"utf16_units":24} +{"code_points":22,"exact":"$𝑥$","id":"astral","plain":"Let $𝑥$ vary with $𝑦$.","runs":[{"kind":"text","text":"Let "},{"kind":"math","notation":"tex","source":"𝑥"},{"kind":"text","text":" vary with "},{"kind":"math","notation":"tex","source":"𝑦"},{"kind":"text","text":"."}],"span":[4,7],"utf16_span":[4,8],"utf16_units":24} diff --git a/vectors/projection-groups.jsonl b/vectors/projection-groups.jsonl new file mode 100644 index 0000000..4559ac0 --- /dev/null +++ b/vectors/projection-groups.jsonl @@ -0,0 +1,11 @@ +{"cases":["h2o-math","h2o-split-math","h2o-mathrm","h2o-sub","h2o-unicode","h2o-typst"],"id":"h2o","same":"match_hash"} +{"cases":["wavenumber-unicode","wavenumber-sup","wavenumber-math","wavenumber-typst"],"id":"wavenumber","same":"match_hash"} +{"cases":["milli-unicode","milli-sup","milli-math"],"id":"milli","same":"match_hash"} +{"cases":["kr-math","kr-mathrm","kr-sub","kr-unicode"],"id":"kr","same":"match_hash"} +{"cases":["ligature","no-ligature"],"id":"ligature","same":"match_hash"} +{"cases":["micro-sign","greek-mu"],"id":"micro","same":"match_hash"} +{"cases":["lost-superscript","superscript"],"id":"103-align","same":"align_key"} +{"cases":["lost-superscript","superscript"],"differ":"match_hash","id":"103-match"} +{"cases":["cite-mark","cite-as-text"],"differ":"match_hash","id":"cite-structure"} +{"cases":["hyphen-before-digit","en-dash-before-digit"],"id":"dashes-align","same":"align_key"} +{"cases":["hyphen-before-digit","en-dash-before-digit"],"differ":"text_hash","id":"dashes-text"} diff --git a/vectors/projections.jsonl b/vectors/projections.jsonl new file mode 100644 index 0000000..80022df --- /dev/null +++ b/vectors/projections.jsonl @@ -0,0 +1,29 @@ +{"align_key":"bd1193ec5e58680b96a5c7b0d8200e1b42f1ff74a7b6ddc4858d470e949cbf9a","complex":[],"id":"h2o-math","lossy":"thesolventish2o.","match_hash":"45ae8b6b0b3c7c0acea0ab1bb873f0afbddb1a3cc7bae762a6304e86d8e11442","normalized":"The solvent is $H_2O$.","plain":"The solvent is $H_2O$.","runs":[{"kind":"text","text":"The solvent is "},{"kind":"math","notation":"tex","source":"H_2O"},{"kind":"text","text":"."}],"strict":"The solvent is H_{2}O.","text_hash":"db7febd83f01411039085c52f807f536ab9307f2a89f04a18dac9f744d4d9a38"} +{"align_key":"bd1193ec5e58680b96a5c7b0d8200e1b42f1ff74a7b6ddc4858d470e949cbf9a","complex":[],"id":"h2o-split-math","lossy":"thesolventish2o.","match_hash":"45ae8b6b0b3c7c0acea0ab1bb873f0afbddb1a3cc7bae762a6304e86d8e11442","normalized":"The solvent is H$_2$O.","plain":"The solvent is H$_2$O.","runs":[{"kind":"text","text":"The solvent is H"},{"kind":"math","notation":"tex","source":"_2"},{"kind":"text","text":"O."}],"strict":"The solvent is H_{2}O.","text_hash":"11cb89a8460bd1c34d530f70474695ff301ed1a320ee2d9ef297fa42b6607cb4"} +{"align_key":"bd1193ec5e58680b96a5c7b0d8200e1b42f1ff74a7b6ddc4858d470e949cbf9a","complex":[],"id":"h2o-mathrm","lossy":"thesolventish2o.","match_hash":"45ae8b6b0b3c7c0acea0ab1bb873f0afbddb1a3cc7bae762a6304e86d8e11442","normalized":"The solvent is $\\mathrm{H}_{2}\\mathrm{O}$.","plain":"The solvent is $\\mathrm{H}_{2}\\mathrm{O}$.","runs":[{"kind":"text","text":"The solvent is "},{"kind":"math","notation":"tex","source":"\\mathrm{H}_{2}\\mathrm{O}"},{"kind":"text","text":"."}],"strict":"The solvent is H_{2}O.","text_hash":"c1123ca8e33cce46335fdb27d94cf25a725fc6fa5e3c490faf590dbe7d74a12b"} +{"align_key":"bd1193ec5e58680b96a5c7b0d8200e1b42f1ff74a7b6ddc4858d470e949cbf9a","complex":[],"id":"h2o-sub","lossy":"thesolventish2o.","match_hash":"45ae8b6b0b3c7c0acea0ab1bb873f0afbddb1a3cc7bae762a6304e86d8e11442","normalized":"The solvent is H2O.","plain":"The solvent is H2O.","runs":[{"kind":"text","text":"The solvent is H"},{"kind":"text","style":["sub"],"text":"2"},{"kind":"text","text":"O."}],"strict":"The solvent is H_{2}O.","text_hash":"4eda9afcb99d2e6ee8ccebdda0162bab85dc96efdaff38fd6dbc898c661ca91a"} +{"align_key":"bd1193ec5e58680b96a5c7b0d8200e1b42f1ff74a7b6ddc4858d470e949cbf9a","complex":[],"id":"h2o-unicode","lossy":"thesolventish2o.","match_hash":"45ae8b6b0b3c7c0acea0ab1bb873f0afbddb1a3cc7bae762a6304e86d8e11442","normalized":"The solvent is H₂O.","plain":"The solvent is H₂O.","runs":[{"kind":"text","text":"The solvent is H₂O."}],"strict":"The solvent is H_{2}O.","text_hash":"2c0dd2f6a6adb414aa2fd642276c0cb5d0cf2248ef2cfc3b0ed77f2332aa2129"} +{"align_key":"bd1193ec5e58680b96a5c7b0d8200e1b42f1ff74a7b6ddc4858d470e949cbf9a","complex":[],"id":"h2o-typst","lossy":"thesolventish2o.","match_hash":"45ae8b6b0b3c7c0acea0ab1bb873f0afbddb1a3cc7bae762a6304e86d8e11442","normalized":"The solvent is $H_2 O$.","plain":"The solvent is $H_2 O$.","runs":[{"kind":"text","text":"The solvent is "},{"kind":"math","notation":"typst","source":"H_2 O"},{"kind":"text","text":"."}],"strict":"The solvent is H_{2}O.","text_hash":"ed0698f969e83d036babeee757eddede4fd4cba5b4f3af336644f5a8c6808954"} +{"align_key":"9467109667c9a35fb2df6a06327af4c63ef511a45e1a50e2c9386796d52d8bc9","complex":[],"id":"wavenumber-unicode","lossy":"abandnear1595cm−1.","match_hash":"d234490f1f606604bc9ff4f4c619bb81c91cc2683c0dd2cf412c9b03daf116bc","normalized":"A band near 1595 cm⁻¹.","plain":"A band near 1595 cm⁻¹.","runs":[{"kind":"text","text":"A band near 1595 cm⁻¹."}],"strict":"A band near 1595 cm^{−1}.","text_hash":"f9f6d5a155dadc7a3616969582c1d6f635185e17f41b88be611e8eb5f4e3a539"} +{"align_key":"9467109667c9a35fb2df6a06327af4c63ef511a45e1a50e2c9386796d52d8bc9","complex":[],"id":"wavenumber-sup","lossy":"abandnear1595cm−1.","match_hash":"d234490f1f606604bc9ff4f4c619bb81c91cc2683c0dd2cf412c9b03daf116bc","normalized":"A band near 1595 cm-1.","plain":"A band near 1595 cm-1.","runs":[{"kind":"text","text":"A band near 1595 cm"},{"kind":"text","style":["sup"],"text":"-1"},{"kind":"text","text":"."}],"strict":"A band near 1595 cm^{−1}.","text_hash":"432ef2dda04d532b8e81febdff75b6a7f69bfe88fd8020518b3741c486f0cc51"} +{"align_key":"9467109667c9a35fb2df6a06327af4c63ef511a45e1a50e2c9386796d52d8bc9","complex":[],"id":"wavenumber-math","lossy":"abandnear1595cm−1.","match_hash":"d234490f1f606604bc9ff4f4c619bb81c91cc2683c0dd2cf412c9b03daf116bc","normalized":"A band near 1595 $\\mathrm{cm}^{-1}$.","plain":"A band near 1595 $\\mathrm{cm}^{-1}$.","runs":[{"kind":"text","text":"A band near 1595 "},{"kind":"math","notation":"tex","source":"\\mathrm{cm}^{-1}"},{"kind":"text","text":"."}],"strict":"A band near 1595 cm^{−1}.","text_hash":"058f804ca85bd2742b40f871798e4697029ac1d34ae3fe84f08ea4549b771149"} +{"align_key":"9467109667c9a35fb2df6a06327af4c63ef511a45e1a50e2c9386796d52d8bc9","complex":[],"id":"wavenumber-typst","lossy":"abandnear1595cm−1.","match_hash":"d234490f1f606604bc9ff4f4c619bb81c91cc2683c0dd2cf412c9b03daf116bc","normalized":"A band near 1595 $\"cm\"^(-1)$.","plain":"A band near 1595 $\"cm\"^(-1)$.","runs":[{"kind":"text","text":"A band near 1595 "},{"kind":"math","notation":"typst","source":"\"cm\"^(-1)"},{"kind":"text","text":"."}],"strict":"A band near 1595 cm^{−1}.","text_hash":"40c687f3ba83dadcd1c577c804b5621ca334637d3e227026b4c9b1a5f4b2c85e"} +{"align_key":"8644140828bf1f481bb4afde325e12197b5284340e23a2c4defbfefd0db93398","complex":[],"id":"milli-unicode","lossy":"valuesbelow10−3weredropped.","match_hash":"402f18f84b6f9883c8014d2f7cf6278e6f5524f92079b1d0442debf544932fa0","normalized":"Values below 10⁻³ were dropped.","plain":"Values below 10⁻³ were dropped.","runs":[{"kind":"text","text":"Values below 10⁻³ were dropped."}],"strict":"Values below 10^{−3} were dropped.","text_hash":"01f80701006bb83a888b131f807424e880c379d290dfe579209f27ea544e4693"} +{"align_key":"8644140828bf1f481bb4afde325e12197b5284340e23a2c4defbfefd0db93398","complex":[],"id":"milli-sup","lossy":"valuesbelow10−3weredropped.","match_hash":"402f18f84b6f9883c8014d2f7cf6278e6f5524f92079b1d0442debf544932fa0","normalized":"Values below 10−3 were dropped.","plain":"Values below 10−3 were dropped.","runs":[{"kind":"text","text":"Values below 10"},{"kind":"text","style":["sup"],"text":"−3"},{"kind":"text","text":" were dropped."}],"strict":"Values below 10^{−3} were dropped.","text_hash":"f85ff38541d4ef7c42982c0a6225a5159ddba3c3b03d554252b3e3fd9262cc70"} +{"align_key":"8644140828bf1f481bb4afde325e12197b5284340e23a2c4defbfefd0db93398","complex":[],"id":"milli-math","lossy":"valuesbelow10−3weredropped.","match_hash":"402f18f84b6f9883c8014d2f7cf6278e6f5524f92079b1d0442debf544932fa0","normalized":"Values below $10^{-3}$ were dropped.","plain":"Values below $10^{-3}$ were dropped.","runs":[{"kind":"text","text":"Values below "},{"kind":"math","notation":"tex","source":"10^{-3}"},{"kind":"text","text":" were dropped."}],"strict":"Values below 10^{−3} were dropped.","text_hash":"510f7ffdcde8465761ee0be1277ea0c4a2ee2c3dbeeff66197c2b1e2a593967e"} +{"align_key":"347038bde4eb9ddd4b7ead7285ffdcfd9296af9507fc2be04eae503b10290241","complex":[],"id":"kr-math","lossy":"theconstantkrislarge.","match_hash":"bcb9eafe84c3d52780bae37e433c0a25de552fc5c39efc6c0a2573ff74b9de78","normalized":"The constant $K_r$ is large.","plain":"The constant $K_r$ is large.","runs":[{"kind":"text","text":"The constant "},{"kind":"math","notation":"tex","source":"K_r"},{"kind":"text","text":" is large."}],"strict":"The constant K_{r} is large.","text_hash":"dfb8290ac5f6841ca8fd16cbf48bf02010db9f2d5bf4534c76bdb9843e630302"} +{"align_key":"347038bde4eb9ddd4b7ead7285ffdcfd9296af9507fc2be04eae503b10290241","complex":[],"id":"kr-mathrm","lossy":"theconstantkrislarge.","match_hash":"bcb9eafe84c3d52780bae37e433c0a25de552fc5c39efc6c0a2573ff74b9de78","normalized":"The constant $K_{\\mathrm{r}}$ is large.","plain":"The constant $K_{\\mathrm{r}}$ is large.","runs":[{"kind":"text","text":"The constant "},{"kind":"math","notation":"tex","source":"K_{\\mathrm{r}}"},{"kind":"text","text":" is large."}],"strict":"The constant K_{r} is large.","text_hash":"1a78c9c621f0743d98f02364c474dfdc1d503f754359c16ac68d6c47d49c84de"} +{"align_key":"347038bde4eb9ddd4b7ead7285ffdcfd9296af9507fc2be04eae503b10290241","complex":[],"id":"kr-sub","lossy":"theconstantkrislarge.","match_hash":"bcb9eafe84c3d52780bae37e433c0a25de552fc5c39efc6c0a2573ff74b9de78","normalized":"The constant Kr is large.","plain":"The constant Kr is large.","runs":[{"kind":"text","text":"The constant K"},{"kind":"text","style":["sub"],"text":"r"},{"kind":"text","text":" is large."}],"strict":"The constant K_{r} is large.","text_hash":"20b700fd3005722f68eba6f8e8656a4c646a77f618a11bd35a18665cfc7f4f5e"} +{"align_key":"347038bde4eb9ddd4b7ead7285ffdcfd9296af9507fc2be04eae503b10290241","complex":[],"id":"kr-unicode","lossy":"theconstantkrislarge.","match_hash":"bcb9eafe84c3d52780bae37e433c0a25de552fc5c39efc6c0a2573ff74b9de78","normalized":"The constant Kᵣ is large.","plain":"The constant Kᵣ is large.","runs":[{"kind":"text","text":"The constant Kᵣ is large."}],"strict":"The constant K_{r} is large.","text_hash":"b636b6aa463b3a8648ef14f81ed699fb2dddd657363c4d35783e0b214d838392"} +{"align_key":"c18a6f3dffdf8fcf355ef258e521f5dac9843bb9fc5d63c71c2d24b87a6f00a3","complex":[],"id":"ligature","lossy":"thefitisgood.","match_hash":"f2cafd933912c4ea86559633994fecbd344dfb0beaf15bf1858685c0ce471b6f","normalized":"The fit is good.","plain":"The fit is good.","runs":[{"kind":"text","text":"The fit is good."}],"strict":"The fit is good.","text_hash":"f9bbe4d605d8a243da53dfb2fc44f2b7b1e5df132116277fce9157a7f9c867f1"} +{"align_key":"c18a6f3dffdf8fcf355ef258e521f5dac9843bb9fc5d63c71c2d24b87a6f00a3","complex":[],"id":"no-ligature","lossy":"thefitisgood.","match_hash":"f2cafd933912c4ea86559633994fecbd344dfb0beaf15bf1858685c0ce471b6f","normalized":"The fit is good.","plain":"The fit is good.","runs":[{"kind":"text","text":"The fit is good."}],"strict":"The fit is good.","text_hash":"f2cafd933912c4ea86559633994fecbd344dfb0beaf15bf1858685c0ce471b6f"} +{"align_key":"20dd97f7d0a3372b59e2dcd3eee64fa213d7ead55dad8bc9e631d62c007c9b83","complex":[],"id":"micro-sign","lossy":"a5μmfilm.","match_hash":"e0266f7562269bc12d6d8bf51c52ffd6511c306b07a0db055aaf3890d7132c5c","normalized":"A 5 µm film.","plain":"A 5 µm film.","runs":[{"kind":"text","text":"A 5 µm film."}],"strict":"A 5 μm film.","text_hash":"0a120e4a1cd7b8f3ca2d4ea4c498dd075ae36be1b4cd78edf7475a3f4bbcff8b"} +{"align_key":"20dd97f7d0a3372b59e2dcd3eee64fa213d7ead55dad8bc9e631d62c007c9b83","complex":[],"id":"greek-mu","lossy":"a5μmfilm.","match_hash":"e0266f7562269bc12d6d8bf51c52ffd6511c306b07a0db055aaf3890d7132c5c","normalized":"A 5 μm film.","plain":"A 5 μm film.","runs":[{"kind":"text","text":"A 5 μm film."}],"strict":"A 5 μm film.","text_hash":"e0266f7562269bc12d6d8bf51c52ffd6511c306b07a0db055aaf3890d7132c5c"} +{"align_key":"c7788ac010791cdfc09f01c87089d499bc92cc558731818b7526a1a622cc7e93","complex":[],"id":"lost-superscript","lossy":"arateof103persecond.","match_hash":"59daf82ed56d0dce4eba9feac195e96c776461d5337deab9f935ff113e920d11","normalized":"A rate of 103 per second.","note":"OCR lost the superscript.","plain":"A rate of 103 per second.","runs":[{"kind":"text","text":"A rate of 103 per second."}],"strict":"A rate of 103 per second.","text_hash":"59daf82ed56d0dce4eba9feac195e96c776461d5337deab9f935ff113e920d11"} +{"align_key":"c7788ac010791cdfc09f01c87089d499bc92cc558731818b7526a1a622cc7e93","complex":[],"id":"superscript","lossy":"arateof103persecond.","match_hash":"bcbd5154f56cbfe39b9c1ad80c0215fe1850106e796dd522669a95d31d4643d5","normalized":"A rate of 10³ per second.","plain":"A rate of 10³ per second.","runs":[{"kind":"text","text":"A rate of 10³ per second."}],"strict":"A rate of 10^{3} per second.","text_hash":"c490b1d6d08e9e0f1bef522f8a78a4f729cf981a7b6fc0c9cc41c1ec479d2115"} +{"align_key":"73b02f8ceb20b94520bc5ca52100c56b14a46d9adb06dbb6c5a19810cf6137e0","complex":[],"id":"cite-mark","lossy":"theenergyislow.","match_hash":"98b2885f074339a8097b6c8c7f2253eb1bb66760684f5e216caccaf224d86d30","normalized":"The energy3 is low.","plain":"The energy3 is low.","runs":[{"kind":"text","text":"The energy"},{"kind":"cite","refs":[],"text":"3"},{"kind":"text","text":" is low."}],"strict":"The energy3 is low.","text_hash":"3166ad5ab03f88cd0c4868ebeb3475b9b3e13036c68ff57d0e6531d4e322fbb1"} +{"align_key":"da65ae55cd55d409477a86e26876cf5f75556c79f612191b5a43af6d553ea0b0","complex":[],"id":"cite-as-text","lossy":"theenergy3islow.","match_hash":"3166ad5ab03f88cd0c4868ebeb3475b9b3e13036c68ff57d0e6531d4e322fbb1","normalized":"The energy3 is low.","plain":"The energy3 is low.","runs":[{"kind":"text","text":"The energy3 is low."}],"strict":"The energy3 is low.","text_hash":"3166ad5ab03f88cd0c4868ebeb3475b9b3e13036c68ff57d0e6531d4e322fbb1"} +{"align_key":"6011a09330d84af0bbfaf227e9e23d8072dccd73513b1fc866df93808b43dd97","complex":["tex:\\frac{1}{2}kx^2"],"id":"complex","lossy":"theenergyisexactly.","match_hash":"d641b65aa2f6b697fd35c8e383e497abe456640af3cdecd28a8120fa92ea9664","normalized":"The energy is $\\frac{1}{2} k x^2$ exactly.","plain":"The energy is $\\frac{1}{2} k x^2$ exactly.","runs":[{"kind":"text","text":"The energy is "},{"kind":"math","notation":"tex","source":"\\frac{1}{2} k x^2"},{"kind":"text","text":" exactly."}],"strict":"The energy is  exactly.","text_hash":"d5a85176f4a53f91916b130e0b35b298e1b999132a6a925b4eccf8f20f2574b5"} +{"align_key":"156cc56f1b8c79722ce3db0aec57879a4b2f467fdb69d75ac6bdae01b7bd4433","complex":[],"id":"hyphen-before-digit","lossy":"pages10−20andctctwith6−31g*","match_hash":"86f127250e5076b9c8b9b5c189361aed13705d1ceb7600cbe2b7ed07597a2313","normalized":"pages 10-20 and CT–CT with 6-31G*","plain":"pages 10-20 and CT–CT with 6-31G*","runs":[{"kind":"text","text":"pages 10-20 and CT–CT with 6-31G*"}],"strict":"pages 10−20 and CT–CT with 6−31G*","text_hash":"9dc7ad6bb0693572f0700420e1b2b1c723b39058784c76154e88fffa8fa0c8a8"} +{"align_key":"156cc56f1b8c79722ce3db0aec57879a4b2f467fdb69d75ac6bdae01b7bd4433","complex":[],"id":"en-dash-before-digit","lossy":"pages10−20andctctwith6−31g*","match_hash":"1d9c138f8b902b350a1f4477e8b84b6a0a87f35a1dd38486112b7291db3aa150","normalized":"pages 10–20 and CT-CT with 6–31G*","plain":"pages 10–20 and CT-CT with 6–31G*","runs":[{"kind":"text","text":"pages 10–20 and CT-CT with 6–31G*"}],"strict":"pages 10−20 and CT-CT with 6−31G*","text_hash":"70b2e77b3966f2c506d87c12b13ebf7ae5193092f678eb101310f363d0ab605a"} +{"align_key":"89658229bf51901882aae4f9543338d4321e4b666a2c191bca749e384fd0a1cc","complex":["tex:𝑥"],"id":"astral","lossy":"letvary.","match_hash":"3b6c539092c6c721ee808437e208b31a1fab3407b43d85e60d29edb65762ac20","normalized":"Let $𝑥$ vary.","plain":"Let $𝑥$ vary.","runs":[{"kind":"text","text":"Let "},{"kind":"math","notation":"tex","source":"𝑥"},{"kind":"text","text":" vary."}],"strict":"Let  vary.","text_hash":"43800bdb4e70f3613083dfe5ce728cf643a1d0d97d321f04cfbb4f9b2e56fc6f"} diff --git a/vectors/proofs.jsonl b/vectors/proofs.jsonl new file mode 100644 index 0000000..d89fa54 --- /dev/null +++ b/vectors/proofs.jsonl @@ -0,0 +1,53 @@ +{"id":"empty-history","items":[],"kind":"root","root":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"} +{"id":"inclusion-0-of-1","index":0,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"]],"kind":"inclusion","leaf":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","path":[],"root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","size":1} +{"from":0,"from_root":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","id":"consistency-0-to-1","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"]],"kind":"consistency","path":[],"to":1,"to_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d"} +{"from":1,"from_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","id":"consistency-1-to-1","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"]],"kind":"consistency","path":[],"to":1,"to_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d"} +{"id":"inclusion-0-of-2","index":0,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"]],"kind":"inclusion","leaf":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809"],"root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","size":2} +{"id":"inclusion-1-of-2","index":1,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"]],"kind":"inclusion","leaf":"a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","path":["75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d"],"root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","size":2} +{"from":0,"from_root":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","id":"consistency-0-to-2","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"]],"kind":"consistency","path":[],"to":2,"to_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"} +{"from":1,"from_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","id":"consistency-1-to-2","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"]],"kind":"consistency","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809"],"to":2,"to_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"} +{"from":2,"from_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","id":"consistency-2-to-2","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"]],"kind":"consistency","path":[],"to":2,"to_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"} +{"id":"inclusion-0-of-3","index":0,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"kind":"inclusion","leaf":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963"],"root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68","size":3} +{"id":"inclusion-1-of-3","index":1,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"kind":"inclusion","leaf":"a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","path":["75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963"],"root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68","size":3} +{"id":"inclusion-2-of-3","index":2,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"kind":"inclusion","leaf":"155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","path":["0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"],"root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68","size":3} +{"from":0,"from_root":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","id":"consistency-0-to-3","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"kind":"consistency","path":[],"to":3,"to_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68"} +{"from":1,"from_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","id":"consistency-1-to-3","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"kind":"consistency","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963"],"to":3,"to_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68"} +{"from":2,"from_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","id":"consistency-2-to-3","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"kind":"consistency","path":["155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963"],"to":3,"to_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68"} +{"from":3,"from_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68","id":"consistency-3-to-3","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"]],"kind":"consistency","path":[],"to":3,"to_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68"} +{"id":"inclusion-0-of-4","index":0,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"inclusion","leaf":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f"],"root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62","size":4} +{"id":"inclusion-1-of-4","index":1,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"inclusion","leaf":"a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","path":["75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f"],"root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62","size":4} +{"id":"inclusion-2-of-4","index":2,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"inclusion","leaf":"155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","path":["22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"],"root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62","size":4} +{"id":"inclusion-3-of-4","index":3,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"inclusion","leaf":"22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","path":["155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"],"root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62","size":4} +{"from":0,"from_root":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","id":"consistency-0-to-4","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"consistency","path":[],"to":4,"to_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"} +{"from":1,"from_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","id":"consistency-1-to-4","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"consistency","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f"],"to":4,"to_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"} +{"from":2,"from_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","id":"consistency-2-to-4","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"consistency","path":["f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f"],"to":4,"to_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"} +{"from":3,"from_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68","id":"consistency-3-to-4","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"consistency","path":["155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e"],"to":4,"to_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"} +{"from":4,"from_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62","id":"consistency-4-to-4","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"]],"kind":"consistency","path":[],"to":4,"to_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"} +{"id":"inclusion-0-of-5","index":0,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"inclusion","leaf":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978","size":5} +{"id":"inclusion-1-of-5","index":1,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"inclusion","leaf":"a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","path":["75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978","size":5} +{"id":"inclusion-2-of-5","index":2,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"inclusion","leaf":"155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","path":["22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978","size":5} +{"id":"inclusion-3-of-5","index":3,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"inclusion","leaf":"22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","path":["155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978","size":5} +{"id":"inclusion-4-of-5","index":4,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"inclusion","leaf":"94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b","path":["02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"],"root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978","size":5} +{"from":0,"from_root":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","id":"consistency-0-to-5","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"consistency","path":[],"to":5,"to_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978"} +{"from":1,"from_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","id":"consistency-1-to-5","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"consistency","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"to":5,"to_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978"} +{"from":2,"from_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","id":"consistency-2-to-5","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"consistency","path":["f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"to":5,"to_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978"} +{"from":3,"from_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68","id":"consistency-3-to-5","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"consistency","path":["155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"to":5,"to_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978"} +{"from":4,"from_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62","id":"consistency-4-to-5","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"consistency","path":["94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b"],"to":5,"to_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978"} +{"from":5,"from_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978","id":"consistency-5-to-5","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"]],"kind":"consistency","path":[],"to":5,"to_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978"} +{"id":"inclusion-0-of-7","index":0,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"inclusion","leaf":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","size":7} +{"id":"inclusion-1-of-7","index":1,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"inclusion","leaf":"a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","path":["75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","size":7} +{"id":"inclusion-2-of-7","index":2,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"inclusion","leaf":"155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","path":["22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","size":7} +{"id":"inclusion-3-of-7","index":3,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"inclusion","leaf":"22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","path":["155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","size":7} +{"id":"inclusion-4-of-7","index":4,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"inclusion","leaf":"94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b","path":["87e9ab87ec024c9cfd30fe839a2f02f2f44dad594c78f59774c1a58ba281e9fd","ff12f34a1d9874fdfe65567869b8cc1c759d72a365714c3ad7d1867dca11abe5","02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","size":7} +{"id":"inclusion-5-of-7","index":5,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"inclusion","leaf":"87e9ab87ec024c9cfd30fe839a2f02f2f44dad594c78f59774c1a58ba281e9fd","path":["94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b","ff12f34a1d9874fdfe65567869b8cc1c759d72a365714c3ad7d1867dca11abe5","02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","size":7} +{"id":"inclusion-6-of-7","index":6,"items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"inclusion","leaf":"ff12f34a1d9874fdfe65567869b8cc1c759d72a365714c3ad7d1867dca11abe5","path":["79402db6db8436c87978e0b2ae96e4ccf6186dbf3d6ca0595b66706bca101d3b","02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"],"root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","size":7} +{"from":0,"from_root":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","id":"consistency-0-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":[],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":1,"from_root":"75adf0bb057af2a45d1389832649b7981b1ffa7833b7889e25c891756838333d","id":"consistency-1-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":["a2f7dbe48f4a6abbff1ca1098c608aa482e7db93fee638763262f5a55e473809","f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":2,"from_root":"0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","id":"consistency-2-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":["f4f29156d3cf192a33965336e1f11af9ab0be3f7f40c051320c3a610c041df4f","2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":3,"from_root":"06ab1e0f8e62816966b59dc3b93813af34e82ad31122ff4a7513bf2369415b68","id":"consistency-3-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":["155df042da6e5d3a61316f68f4823a809297c625a824cce6e3022015dd328963","22769c621034b270035198ad5355d33aae23af7ab76abc180b296722c054966a","0919534b87e9cc2277960728287d034f6a053cb5f70e268f256f1068cb90cb2e","2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":4,"from_root":"02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62","id":"consistency-4-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":["2c25d6c01a28d122305670909fba19dcc7b3e5566b7094d4fe136a6debedcaf9"],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":5,"from_root":"4b6a23e70edefdbac14f83decd4af78622c35c8ca02b0c1b6329b3b81f32d978","id":"consistency-5-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":["94205244c6aad7fd93e0bb5bd6894caf7b94d39f0bde3f9cd350b744b1209c5b","87e9ab87ec024c9cfd30fe839a2f02f2f44dad594c78f59774c1a58ba281e9fd","ff12f34a1d9874fdfe65567869b8cc1c759d72a365714c3ad7d1867dca11abe5","02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":6,"from_root":"a059493a626fe548376bcedc32ac42cd4e48d024eb508fe216475b8aec9613bf","id":"consistency-6-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":["79402db6db8436c87978e0b2ae96e4ccf6186dbf3d6ca0595b66706bca101d3b","ff12f34a1d9874fdfe65567869b8cc1c759d72a365714c3ad7d1867dca11abe5","02aafed31655132fcbdada47ca422b301a43b479fc87c6db1f9175b823de0e62"],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":7,"from_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274","id":"consistency-7-to-7","items":[["node","k0yqkzd","db87cee52504ca5732bad49ddb1d5b8551c011c1891996d58aacae47f66585ed"],["node","h9haqzy","33112ee14ee469c3eb52fe90322ec81dd404a0093d565a6d71ce77cbc8124e3b"],["node","brghw1a","f998fe06afa0cfbe73e0449dc2b1698309e1b5714960f027b2858312b152c275"],["node","f1csy9e","97fb5f8538b89f6c1accfd19836b65a73b61fbc2e0cbf84bb858a0fffa3f1592"],["node","qqe35f5","e9590c04cea54beb769a96148583176605389b3a3809162f2fd6392b43fb8382"],["node","vm2d8hy","acea77fd89c7fb586c8c7c612b53634c4571a40cf8b1bcecb002311210423f57"],["node","dy199dx","fa37de9da4b13b3a18882ece23d6bee24a329b77d488b984d6f5587ce3f0f6cf"]],"kind":"consistency","path":[],"to":7,"to_root":"7262ec554038131f59848f2761cab84e1c686d3f92a44e1919a78aeb680ea274"} +{"from":8,"from_root":"1fd353414a872011b133a8d53d96bc193e45ac89721237c05da7a671ec09aa5b","id":"hale-history-8-to-12","items":[["correction",1,"vkvk912tasd80"],["correction",2,"va54bce6kgvq0"],["correction",3,"m824p8vy7nrx8"],["correction",4,"dzmfs6cyf89bt"],["correction",5,"m4kckv7dqkjw8"],["correction",6,"v4raw31f93rqa"],["correction",7,"g30d5wph3bqyy"],["correction",8,"s0c7mjf6x0b6v"],["correction",9,"b7hjt11dfg229"],["correction",10,"dz23scwhh30sx"],["correction",11,"wa7sn096vxh3y"],["correction",12,"dx6rkj4hcm7gg"]],"kind":"consistency","path":["970d5333fabc81c33a34b524bb11a21aa6bc808fb15a4b954924d0058ddd69ff"],"to":12,"to_root":"e215570ec1c660164c8b1e8012a9c7de9e98d5e508bf80ffdc2c7cd4cbb5ab0f"} +{"id":"hale-history-correction-5","index":4,"items":[["correction",1,"vkvk912tasd80"],["correction",2,"va54bce6kgvq0"],["correction",3,"m824p8vy7nrx8"],["correction",4,"dzmfs6cyf89bt"],["correction",5,"m4kckv7dqkjw8"],["correction",6,"v4raw31f93rqa"],["correction",7,"g30d5wph3bqyy"],["correction",8,"s0c7mjf6x0b6v"],["correction",9,"b7hjt11dfg229"],["correction",10,"dz23scwhh30sx"],["correction",11,"wa7sn096vxh3y"],["correction",12,"dx6rkj4hcm7gg"]],"kind":"inclusion","leaf":"4191e9c9ec71436e4b4ac20cbe0f1047773425a1789bf81d8b3e854a005b9b17","path":["bbb662e4ff7b2e7bc0e392a653e0587ff2132e47f469190e13dc0f1d9e8839e9","314588141e80ed37ce39f72dfca2a207c3d775eb2c91ab98c680d725ece084cb","6f4d1246b856f66e074e59019f97e12c8a80252782965f898889180a9b61d3f9","970d5333fabc81c33a34b524bb11a21aa6bc808fb15a4b954924d0058ddd69ff"],"root":"e215570ec1c660164c8b1e8012a9c7de9e98d5e508bf80ffdc2c7cd4cbb5ab0f","size":12} diff --git a/vectors/resolve.jsonl b/vectors/resolve.jsonl new file mode 100644 index 0000000..8858360 --- /dev/null +++ b/vectors/resolve.jsonl @@ -0,0 +1,17 @@ +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"hca6dc5","node_hash":"8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34","own_hash":"c270571517825ceed31ca912b80ac76203effe47f1c84f8ee8962800d0afc92f","quote":{"exact":"H$_2$O","prefix":"Water, ","suffix":", served as the first test case,"},"rev":0,"span":[7,13],"store":"smithlab"},"expect":{"node":"hca6dc5","node_hash":"8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34","result":"current","span":[7,13]},"id":"span-current","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"context":{"column_path":["Set A","$K_r$ (kcal mol⁻¹ Å⁻²)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"c20cna6","node_hash":"7252bb19f33a3be672d74a8aa8323750311b5c7d2b8f6cf21e07f17f2b27f3a1","own_hash":"275a7b12827bf7c77ae27a47cccdf9c4e2480d2ab8828de0b548d255bfa8720d","quote":{"exact":"3l0.0"},"rev":0,"store":"smithlab"},"expect":{"node":"c20cna6","node_hash":"c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272","reason":"the node changed and the quote does not occur exactly once","result":"stale"},"id":"leaf-stale","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"context":{"column_path":["Set B","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","CT–CT"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"bnyvykm","node_hash":"13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94","own_hash":"2c4883c8937f42c190c21a096aaf473e1d35587acf796cc0380f2347aac42f15","quote":{"exact":"1.5260"},"rev":0,"store":"smithlab"},"expect":{"node":"bnyvykm","node_hash":"13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94","result":"current"},"id":"leaf-current","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"table-body","leaves":[["a49pag5","deaa884fd6ab00c358507695e45b7f13c55c2c97cd527617be3b8b030d04631f"],["vd76637","670ae760d62ff8d674b222641915f452595b35aa53cdbd5b27194ef13c29e7f4"],["c20cna6","eb36054f18e4fb1c5107c0060e0d6e44a8ca10a40a61d33b5ae78c0470d86862"],["ztww0g8","ee8dce19ea6dd3f91de5a1b9d9c13c2077c462523d14b5cd9958749e6b58d7e6"],["j6y45v6","6b8d9cf3fe1a78784cab97278e5ccfdf305879dd1cd120c3fe6708b529f31b15"],["bnyvykm","c649510dde8e1cdf382f42a071e5fa75089e908840c9e8d1aa30ff514b2379e4"],["k03dm2e","8e626647307dc064d96fb93c50b4c6c5cab90f9369f00a7252a004a0c9871ee3"],["qacy341","f30130f6a42898d5d87ecd4d8503854dd79a2b6ea87b769fe994ce7f8ec52b29"],["ex460rm","1bec39b32c2e32386d9d6782efca347244c62b4c431e4dc2a55481a5da7f704d"],["w97feam","f86dc724b46c39587e180a46b910d9b3a9be3421176a03b4beba3bb401a60c5b"]],"node":"dwwm2fa","node_hash":"babf79f5b7d6b5e4771878a29489cac0975fd80b3fd0bba67b9491339a1a960b","own_hash":"b229a7f92314227bf225ad27010a546e7c2373f4b30b7f6ec372e568cbacb6aa","rev":0,"store":"smithlab"},"expect":{"drift":{"count":4,"level":"high","share":"0.7500"},"node":"dwwm2fa","node_hash":"bbc57601027c304301fce03f406b68445e00b79c38a886c5a4da8c9f217a358c","result":"changed-below"},"id":"body-drift-high","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"table","node":"hj4s7pb","node_hash":"578b9b49eff8aa2ebb6c41c2a7b429972d516e5488e0a11eab67071149ed4fea","own_hash":"66310a9ab1c92568f4c6cae012e35d4245d4ca4b89d2542b7c2113a31ad379ed","rev":0,"store":"smithlab"},"expect":{"drift":{"count":5,"level":"high","share":"0.5517"},"node":"hj4s7pb","node_hash":"6c6fba200faf41cd06fa8b64e06e2aa29ff8848568b859ae42d1902596348643","result":"changed-below"},"id":"table-changed-below","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"section","node":"d400rz3","node_hash":"fc81281c8ecf8e2025e6fc47aa4c3c4f2662a30c0c73e2a1c5fbe11d3c6d8207","own_hash":"c3d50f266b05d7889c001aef16662cecd4e99ac4a2747ec331c1044e6adc8e3e","rev":0,"store":"smithlab"},"expect":{"drift":{"count":8,"level":"high","share":"0.5263"},"node":"d400rz3","node_hash":"e5a8eeb3c112f2dc3341da8f433540a3fc5a7e7f631e72c4dd36c6933aae808d","result":"changed-below"},"id":"section-changed-below","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"ec5jc93","node_hash":"b3438d99a16eb6944e032b4413b9153d353465dd351103cee6549c71c0221ee7","own_hash":"322ad8bcec3761e766bf690330a394fd88d2c360ce04425ccb81ac18fb9130fb","quote":{"exact":"treated as zero","prefix":"lues below 10-3 kcal mol⁻¹ were ","suffix":". Table 1 lists the fitted const"},"rev":0,"span":[34,49],"store":"smithlab"},"expect":{"node":"ec5jc93","node_hash":"5421e9cf0ef3a995792963d0371b79e11a8efad519b02efb5cb88311a896d0cc","result":"reattached","span":[34,49]},"id":"span-reattached","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"ec5jc93","node_hash":"b3438d99a16eb6944e032b4413b9153d353465dd351103cee6549c71c0221ee7","own_hash":"322ad8bcec3761e766bf690330a394fd88d2c360ce04425ccb81ac18fb9130fb","quote":{"exact":"fitted constants","prefix":"ated as zero. Table 1 lists the ","suffix":" for both parameter sets."},"rev":0,"span":[69,85],"store":"smithlab"},"expect":{"node":"ec5jc93","node_hash":"5421e9cf0ef3a995792963d0371b79e11a8efad519b02efb5cb88311a896d0cc","reason":"the node changed and the quote does not occur exactly once","result":"stale"},"id":"span-stale-after-split","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"ayea71r","node_hash":"d7c13d8c4e3588f236945b69f73cc2e94249fb697a2e841b5823cc3e23983616","own_hash":"752ebe6e130df9e8f91ffba7ed770e2df599be3399c40c97c780ef86ada1bb5f","quote":{"exact":"least squares","prefix":"fitted by ","suffix":"."},"rev":0,"span":[10,23],"store":"smithlab"},"expect":{"node":"xjns57z","node_hash":"42b1de7852cdc68730984fff789fe248ecd5b43198c0e7d671931ff3fe561dc3","result":"moved","span":[93,106],"via":["ayea71r"]},"id":"span-moved-by-merge","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"v8e4z6z","node_hash":"2c4fadc156966ad797dfc7db9d4c0bae120c1df8586ee6a6d2976056dec7091e","own_hash":"1166e91d94a8130b1829b3e66b182febe6c2eb75b7f54e08f9af8571eaa085f9","quote":{"exact":"J. Example Chem. 2026, 14, 101–109"},"rev":0,"store":"smithlab"},"expect":{"node":null,"reason":"retired without a successor","result":"stale","via":["v8e4z6z"]},"id":"leaf-deleted","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"equation","node":"tkxsmts","node_hash":"47227b3e48e70a28623a93f19deda7414ebeff9d04fa00522874112249f2387b","own_hash":"fae526da7101762cc32b2cdd8dbcb254bc4c809fa6dc491c76c51e9b0bc0dc81","quote":{"exact":"$$E_{\\mathrm{bond}} = \\frac{1}{2} K_r (r - r_{\\mathrm{eq}})^2$$"},"rev":0,"store":"smithlab"},"expect":{"node":"tkxsmts","node_hash":"cc0bf73dd84e298da0d36c4b363c8d2bdc9b6d5738d1923d14c4a9028dca08d6","result":"reattached"},"id":"equation-reattached","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"figure","node":"v7cx6qs","node_hash":"dad89409c8a3108d0c17c8d1625a448c7920f50876dc68fd382a1114f56934ee","own_hash":"1933616f3f17e12f7da97bb43de32cdd047800157043f6972e7eaccff9f6f52f","rev":0,"store":"smithlab"},"expect":{"node":"v7cx6qs","node_hash":"f76864779843485fa9e2f3cc3cd1c76ad222e1649c56f4cface33bf20b8f33b6","reason":"relabel","result":"reattached"},"id":"figure-relabel","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"context":{"column_path":["Set A","$r_\\mathrm{eq}$ (Å)"],"row_path":["Bond parameters","CT–HC"],"table_label":"Table 1"},"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"cell","node":"ex460rm","node_hash":"9635a750ac2acf526a4db28746fd3ed84659f4e384f5a73fef85d002b4e9308b","own_hash":"5ecf316bd05e3dc1c6c623bf7041b990d76cbd5d945ba6f0288ec035aedf958e","quote":{"exact":"1.090"},"rev":0,"store":"smithlab"},"expect":{"node":"b5gd0h1","node_hash":"9635a750ac2acf526a4db28746fd3ed84659f4e384f5a73fef85d002b4e9308b","result":"reattached","via":["ex460rm"]},"id":"cell-header-paths","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"sentence","node":"b-p01-text-003","node_hash":"8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34","own_hash":"c270571517825ceed31ca912b80ac76203effe47f1c84f8ee8962800d0afc92f","quote":{"exact":"first test case","prefix":"Water, H$_2$O, served as the ","suffix":", with a bending band near 1595 "},"rev":0,"span":[29,44],"store":"smithlab"},"expect":{"node":"hca6dc5","node_hash":"8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34","result":"current","span":[29,44],"via":["b-p01-text-003"]},"id":"via-alias","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"paragraph","leaves":[["xjns57z","a585745f00df6e0c769ccc7d11894670faacf1d94d24a39da8e4986e3f758237"],["ayea71r","701f05ec607477508a5be4207ec979941cb7ccbcb60bba8e5d7b86558d44e4cd"]],"node":"gwzbj3s","node_hash":"19bc20e19c6912bfe48b4f798e20b37efec81d63231d5565de2c270aced992db","own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","rev":0,"store":"smithlab"},"expect":{"drift":{"count":1,"level":"high","share":"0.6667"},"node":"gwzbj3s","node_hash":"ff27c79f4138e71ef9fccdaab2cea2bcc7db17b7d75e2c806252a14bba9ce530","result":"changed-below"},"id":"paragraph-changed-below","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"row","leaves":[["vd76637","670ae760d62ff8d674b222641915f452595b35aa53cdbd5b27194ef13c29e7f4"],["c20cna6","eb36054f18e4fb1c5107c0060e0d6e44a8ca10a40a61d33b5ae78c0470d86862"],["ztww0g8","ee8dce19ea6dd3f91de5a1b9d9c13c2077c462523d14b5cd9958749e6b58d7e6"],["j6y45v6","6b8d9cf3fe1a78784cab97278e5ccfdf305879dd1cd120c3fe6708b529f31b15"],["bnyvykm","c649510dde8e1cdf382f42a071e5fa75089e908840c9e8d1aa30ff514b2379e4"]],"node":"g8d2pjb","node_hash":"9a065e344a3aa43e715e67547b5f0ea2a0a87c50d903c5ecad1d8f966a76901f","own_hash":"6c7c11bf1b6260162c4141f1468aa6869f5c33359900497e2cdb1a051488bd62","rev":0,"store":"smithlab"},"expect":{"drift":{"count":1,"level":"low","share":"0.2000"},"node":"g8d2pjb","node_hash":"5b3fb4e1cd577e8dfb6e4fc710f537e6a5b5e5178b6657dea49ba0cd94732851","result":"changed-below"},"id":"row-drift-low","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchor":{"doc":"hale2026harmonic-damb","format":"scienting-anchor/1","kind":"paragraph","leaves":[["qwgfg51","a86a8326bd265e4ddc24c02c243e8a73ae33899886643be7eb61cd4e0f21ae7a"]],"node":"ncx2v4f","node_hash":"4a868033f19b957786ca823a7f0d20be200f246415d5d667fa0db9998fafabc1","own_hash":"494e069be36a18ecaabf5a63be7c31617ade7a5460218ca83a2de3d8d8f964e0","rev":0,"store":"smithlab"},"expect":{"node":"gwzbj3s","node_hash":"ff27c79f4138e71ef9fccdaab2cea2bcc7db17b7d75e2c806252a14bba9ce530","result":"moved","via":["ncx2v4f"]},"id":"paragraph-moved","package":"fixtures/packages/hale2026harmonic-damb"} diff --git a/vectors/rights.jsonl b/vectors/rights.jsonl new file mode 100644 index 0000000..2e90d3f --- /dev/null +++ b/vectors/rights.jsonl @@ -0,0 +1,14 @@ +{"expect":{"allowed":true,"expired":false,"lacking":[]},"id":"convert-local","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[],"processor":"local","requires":{"ai":{"purpose":"internal"},"note":"Conversion by any model, local or outside.","uses":["tdm"]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"convert-model","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":false,"expired":false,"lacking":["ai/internal/outside"]},"id":"convert-outside","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[],"processor":"outside","requires":{"ai":{"purpose":"internal"},"note":"Conversion by any model, local or outside.","uses":["tdm"]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"convert-model","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":false,"expired":false,"lacking":["ai/internal/tenancy?"]},"id":"review-tenancy-unknown","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[],"processor":"tenancy","requires":{"ai":{"purpose":"internal"},"note":"Model review of suspects, in a job zip or the direct API mode.","uses":[]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"review-model","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":true,"expired":false,"lacking":[]},"id":"review-tenancy-policy","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[{"applies_to":{"basis":["subscription"],"doi_prefixes":["10.5555/"]},"at":"2026-10-05T09:00:00Z","by":"ana","format":"scienting-policy/1","id":"g6r348z7ckp4q","project":"smithlab-charges","signature":{"key":"ana","scheme":"ed25519","value":"FLg+kUV7cf0v+t8tGkYEtKdEazsqBb7X2LTqRHmMXH3h3ue/SXiegRBFxgIKff28elJSFv5EG7dK9LqvOs+PAA=="},"statement":"Our institutional agreement covers internal AI use in our own cloud account for these papers (fictional).","uses":{"ai":{"internal/tenancy":true}},"valid_until":"2027-08-31T23:59:59Z"}],"processor":"tenancy","requires":{"ai":{"purpose":"internal"},"note":"Model review of suspects, in a job zip or the direct API mode.","uses":[]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"review-model","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":true,"expired":false,"lacking":[]},"id":"index","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[],"processor":"local","requires":{"note":"The full-text index.","uses":["tdm"]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"index","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":false,"expired":false,"lacking":["processor:outside-no-retention","ai/internal/outside-no-retention?"]},"id":"embed-outside-refused","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[{"applies_to":{"basis":["subscription"],"doi_prefixes":["10.5555/"]},"at":"2026-10-05T09:00:00Z","by":"ana","format":"scienting-policy/1","id":"g6r348z7ckp4q","project":"smithlab-charges","signature":{"key":"ana","scheme":"ed25519","value":"FLg+kUV7cf0v+t8tGkYEtKdEazsqBb7X2LTqRHmMXH3h3ue/SXiegRBFxgIKff28elJSFv5EG7dK9LqvOs+PAA=="},"statement":"Our institutional agreement covers internal AI use in our own cloud account for these papers (fictional).","uses":{"ai":{"internal/tenancy":true}},"valid_until":"2027-08-31T23:59:59Z"}],"processor":"outside-no-retention","requires":{"ai":{"processors":["local","tenancy"],"purpose":"internal"},"note":"Embeddings for search.","uses":[]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"embed","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":false,"expired":false,"lacking":["quote-public"]},"id":"publish-quotes","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[],"processor":"local","requires":{"note":"Publishing anything with quotations.","uses":["quote-public"]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"publish-quotes","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":false,"expired":true,"lacking":["read"]},"id":"read-expired","now":"2027-09-01T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[],"processor":"local","requires":{"note":"Reading in the reader.","uses":["read"]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"read","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"allowed":false,"expired":false,"lacking":["accessible-copy?"]},"id":"accessible-copy-unknown","now":"2026-10-11T00:00:00Z","origin":{"doi":"10.5555/example.hale.2026","retrieved_at":"2026-10-01T08:00:00Z","source":"publisher"},"policies":[],"processor":"local","requires":{"note":"An accessible copy for a user with a disability.","uses":["accessible-copy"]},"rights":{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"},"stage":"accessible-copy","witness_sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"} +{"expect":{"accessible-copy":"unknown","ai/external/local":false,"ai/external/outside":false,"ai/external/outside-no-retention":false,"ai/external/tenancy":false,"ai/internal/local":true,"ai/internal/outside":false,"ai/internal/outside-no-retention":"unknown","ai/internal/tenancy":"unknown","quote-public":false,"read":true,"redistribute":false,"tdm":true},"id":"combine","rights":[{"asserted_by":{"by":"crossref","evidence":[{"doi":"10.5555/example.okafor.2025","kind":"crossref-license","url":"https://creativecommons.org/licenses/by/4.0/"}]},"at":"2026-09-15T12:00:00Z","basis":"open-license","format":"scienting-rights/1","license":{"spdx":"CC-BY-4.0","url":"https://creativecommons.org/licenses/by/4.0/"},"uses":{"accessible-copy":true,"ai":{"external/local":true,"external/outside":true,"external/outside-no-retention":true,"external/tenancy":true,"internal/local":true,"internal/outside":true,"internal/outside-no-retention":true,"internal/tenancy":true},"quote-public":true,"read":true,"redistribute":true,"tdm":true},"valid_until":null},{"asserted_by":{"by":"ana","evidence":[{"kind":"statement","note":"The library's subscription terms, as the team read them (fictional)."}]},"at":"2026-09-15T12:00:00Z","basis":"subscription","format":"scienting-rights/1","license":{"text":"Publisher's subscription terms (fictional)."},"uses":{"accessible-copy":"unknown","ai":{"external/local":false,"external/outside":false,"external/outside-no-retention":false,"external/tenancy":false,"internal/local":true,"internal/outside":false,"internal/outside-no-retention":"unknown","internal/tenancy":"unknown"},"quote-public":false,"read":true,"redistribute":false,"tdm":true},"valid_until":"2027-08-31T23:59:59Z"}]} +{"backend":{"code_license":{"spdx":"MIT"},"conditions":[],"format":"scienting-backend/1","name":"docling","processor":"local","stage":"read","version":"illustrative","weights":[{"license":{"spdx":"Apache-2.0"},"name":"layout model"}]},"expect":{"allowed":true,"failed":[]},"id":"backend-docling-smithlab","profile":{"at":"2026-10-01T00:00:00Z","competes_with":[],"format":"scienting-profile/1","purpose":"research","recorded_by":"ana","revenue_or_funding_usd":{"at_most":2000000},"team":"smithlab"}} +{"backend":{"code_license":{"spdx":"MIT"},"conditions":[],"format":"scienting-backend/1","name":"docling","processor":"local","stage":"read","version":"illustrative","weights":[{"license":{"spdx":"Apache-2.0"},"name":"layout model"}]},"expect":{"allowed":true,"failed":[]},"id":"backend-docling-acme","profile":{"at":"2026-10-01T00:00:00Z","competes_with":null,"format":"scienting-profile/1","purpose":"commercial","recorded_by":"acme-admin","revenue_or_funding_usd":{"at_most":null},"team":"acme"}} +{"backend":{"code_license":{"spdx":"Apache-2.0"},"conditions":[{"id":"revenue-cap","kind":"revenue-cap","usd":5000000},{"id":"no-competition","kind":"no-competition","vendor":"examplevendor"},{"allowed":["research","personal","education","startup"],"id":"purpose","kind":"purpose"}],"format":"scienting-backend/1","name":"examplevendor","processor":"local","stage":"read","version":"1.0","weights":[{"license":{"text":"A fictional weight license with conditions."},"name":"example weights"}]},"expect":{"allowed":true,"failed":[]},"id":"backend-examplevendor-smithlab","profile":{"at":"2026-10-01T00:00:00Z","competes_with":[],"format":"scienting-profile/1","purpose":"research","recorded_by":"ana","revenue_or_funding_usd":{"at_most":2000000},"team":"smithlab"}} +{"backend":{"code_license":{"spdx":"Apache-2.0"},"conditions":[{"id":"revenue-cap","kind":"revenue-cap","usd":5000000},{"id":"no-competition","kind":"no-competition","vendor":"examplevendor"},{"allowed":["research","personal","education","startup"],"id":"purpose","kind":"purpose"}],"format":"scienting-backend/1","name":"examplevendor","processor":"local","stage":"read","version":"1.0","weights":[{"license":{"text":"A fictional weight license with conditions."},"name":"example weights"}]},"expect":{"allowed":false,"failed":["revenue-cap","no-competition","purpose"]},"id":"backend-examplevendor-acme","profile":{"at":"2026-10-01T00:00:00Z","competes_with":null,"format":"scienting-profile/1","purpose":"commercial","recorded_by":"acme-admin","revenue_or_funding_usd":{"at_most":null},"team":"acme"}} diff --git a/vectors/signatures.jsonl b/vectors/signatures.jsonl new file mode 100644 index 0000000..4be6e2d --- /dev/null +++ b/vectors/signatures.jsonl @@ -0,0 +1,6 @@ +{"id":"rfc8032-test-1","message":"","public":"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a","secret":"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60","signature":"e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"} +{"id":"receipt-r1","payload":"{\"format\":\"scienting-receipt/1\",\"hash\":\"ae17f8866a05ca1b671d96b7758984e11ac694acd6743835f107cb513c7cc600\"}","public":"RUiz5j+y0QwgOtsQpqXrlq+gy3c/JFnkxwvlWUNX4Ao=","receipt":{"at":"2026-10-11T15:02:11Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"avbhhey","sha256":"942c23ea73a297e69c2ae8a82abe88d688de2532cb3f6d3543d1107c54f65b2e"},{"kind":"crop","node":"b5gd0h1","sha256":"a0b6f761fe95f8f29ef6dc37901fa85c7a62857b50b0163ca67b0aab048e4d17"},{"kind":"crop","node":"bnyvykm","sha256":"2c560caeaf914f3521fd0e3fca433922fcb9408c184c9b72bcfa869adf5ed409"},{"kind":"crop","node":"c20cna6","sha256":"bdbf7a4d9e86609675e3fc124c21ce808053a52d6bc0f35b15e1ba39027f13af"},{"kind":"crop","node":"d1mhw8b","sha256":"3104c57d9f8fb38302b057ead3bc44456da94f7c17d7c5c8f6db8732d4812c31"},{"kind":"crop","node":"ec5jc93","sha256":"321a926653b9e097987d255d9286880893d71abf895d73f1649403ed9ac0877d"},{"kind":"crop","node":"exms5gc","sha256":"cfc0e42e734470df5cfb741f92080526ef796bf48bcf05847d44f7091cfaaab1"},{"kind":"crop","node":"ganq1ns","sha256":"81d88697cd002fdfd770ee11413c550e4e4ffaa464d35841648311f278fc13bc"},{"kind":"crop","node":"hca6dc5","sha256":"a26619c3a9824bc19fddcf89ee618d9a4792d69110439f121eb717b6f98e88a6"},{"kind":"crop","node":"j6y45v6","sha256":"e689deda15dde9ad24433eb946200417473d273a1bf3136df67bf572256a483f"},{"kind":"crop","node":"jv1741a","sha256":"de60579bacfab769f614fa74d26d20c7b1aa02caf60af1479dc46b98ddcbc106"},{"kind":"crop","node":"k6a6616","sha256":"37b29d7ba293b27f913868690a785591d89ba9a4f47da8adaf764a4d5ae9675b"},{"kind":"crop","node":"m1p1n2g","sha256":"369c69758d2d09cc3d42b2424723c4fbc75f9ceb6817da81ce183be7d36f045f"},{"kind":"crop","node":"rr20tev","sha256":"f57e2cfe704d52c712b01e993e492b121ffe8c4d0174b11a0b0fa21fc5b9930b"},{"kind":"crop","node":"ryhrskg","sha256":"e6f816d93cfff8418dbb771ba03a09fb89a3b2438f97fabfc4ebef7f78af0dbf"},{"kind":"crop","node":"tkxsmts","sha256":"5d8e205660c2c59dcaff119b5671ac11650974b5287d7d7b239a9118e9171a85"},{"kind":"crop","node":"vd76637","sha256":"389742a44f1291e2dc7d7a69acd09410c92ed8a305718b2ab86b0b09b23253f4"},{"kind":"crop","node":"w0gr97q","sha256":"588a38407463e5674714899e6cf359810ccfed98fefdd2c1a90e8cb2ed0a9d64"},{"kind":"crop","node":"w264b74","sha256":"0babb0cef51933b8744f5b22d075069d51e431d3bdc08cb5e35d7822097b5953"},{"kind":"crop","node":"x3ns64d","sha256":"6bd7423a5933eb89572ded1d40d2f5baf6f6fa2f3c46791de8210f201a94b9d1"},{"kind":"crop","node":"ycwgbx1","sha256":"5ee72aca6b32e45f961f9cb2ff70408e71fc9ed7fccd28e91eb86e872041fed3"},{"kind":"crop","node":"yvkd7xr","sha256":"62fd5beecb3e76f430dfd142f443158b84657196af17173a976345a0cdd74449"},{"kind":"crop","node":"ztww0g8","sha256":"902e8ca35e1a313a81130c4c100aeb2233fd53854677b3a992fb16f744fe3151"},{"kind":"witness","sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"}],"format":"scienting-receipt/1","id":"y2zw8ctg5s8dp","level":"F3","nodes":[["avbhhey","c51730c0b1d7e11b51b317163ae42838f1be808b3690f196923482c9021f97c0"],["b5gd0h1","9635a750ac2acf526a4db28746fd3ed84659f4e384f5a73fef85d002b4e9308b"],["bnyvykm","13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94"],["c20cna6","c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272"],["d1mhw8b","557a47334329925d191e772172fddbc1bd1a035eb2217240c476ee6bc43c92ab"],["ec5jc93","5421e9cf0ef3a995792963d0371b79e11a8efad519b02efb5cb88311a896d0cc"],["exms5gc","b7c47f8360eb7272d2ac0943e8bf1aec9d71cb4ea4e5e1d02f8acee5b430a038"],["ganq1ns","40d46db2088057debc3b1d5b4a3c972ff3a94fc3d5463565f98876d0927f1e67"],["hca6dc5","8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34"],["j6y45v6","00c4b92e220303ebc2bfb36aa557ac80ae4dba1675e9ed47adb82f6aeff10634"],["jv1741a","f644190803b5ea36aa24738e7f168a7fdf0d05cb5123c14a814b7628dab71f1e"],["k6a6616","90aa63a43587bdcee8e428c7dc7a95ac1502bdbcb9f49cae05c433db6d18348b"],["m1p1n2g","0847b5d75c2259257c3619e761c64d5571d3ca3932e96a96ee07e8ce68cc63be"],["rr20tev","76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7"],["ryhrskg","525583990e7871a2ba55739e8206abac2df0f19d30c86ad74f6cafdd7c3cbe25"],["tkxsmts","cc0bf73dd84e298da0d36c4b363c8d2bdc9b6d5738d1923d14c4a9028dca08d6"],["vd76637","33810e4da42f8e65a224b5369c06fe8db254890294b7b6760808fe6e039da21a"],["w0gr97q","f738a008336ac59b2f1d45cda2f045dc96d34f0f1378c431ce6ff8e434feb8a7"],["w264b74","2ba9cea0f5c07ee9f7b47c5d541c85e92465709322869fb6c0d994ab61c56cad"],["x3ns64d","6bfc0a055148d877dbaf28b7f62565de7b6926137bf032c382282c39a4876797"],["ycwgbx1","167d1551ca64cad5b1143431c5af6d3fc24530887470b7fd265df88d1f54f267"],["yvkd7xr","aab8791a24bc4067c7e37fc5f0244d2128205e0a169e65c2c0fad977aabce313"],["ztww0g8","bda85639faacb77e504c891c035012602836171c009ecfd21584de4d6461ba93"]],"rev":12,"root":"373a7d860a14b58e5bfa9b9ad3bc916091bcb6db7556f0dbc9c71972a612494d","scope":"targeted:lode","signature":{"key":"ana","scheme":"ed25519","value":"2sraHCMlItocGta02EhvPlDW+F8rB1ZYMXBzA5lmNmtH0h+AlrNOPTbtykVSAWQXfKT2DXuB81/6x5jyNsIVBA=="}},"record_hash":"ae17f8866a05ca1b671d96b7758984e11ac694acd6743835f107cb513c7cc600","record_id":"y2zw8ctg5s8dp"} +{"did":"did:key:z6MktwupdmLXVVqTzCw4i46r4uGyosGXRnR3XjN4Zq7oMMsw","id":"did-key-ed25519","public":"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a","scheme":"ed25519"} +{"did":"did:key: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","id":"did-key-ml-dsa-65","public":"2841528a95e5cda35d99bc8d797774b577b254ca0680de5a07b0fdb75869b5a6a5b9f6e02cd0300fa485623ecc20ee4708a3d93fb4297a4fec246e170c6a5840b1dd6b6f01f138aa8045223d07a3ec11811f562fca76d59feb7a099015e9671acbbecab98c60cc8d1ea6aec39e54079504d970969ae75f028ee17678a528c3e245b2ab08fa54a3ab0f02d73d75c4911fc55c090086699fdc8a4dcd521dfbdc29e484534a9c0ac13984524aa714038d88bcdabb878785d3e7574d74be4339b44ce6c97bf1324a1053c30d1b5a8c1c84dd5d9b94cf7fd0c7e9310d57f0def75377d2ccbacf9c27b06ed27655f7203a16ec5d7995d9b9c202ea436100db185f9b9c4c64f310d177b12ddf5341afd5fa30d1601aff49e21640b99fbc36e6571e55d90d852fe59f7f3de92e8d3104cdeb6cb3b1451e7ea9efc341a0d090dc508bfce5fc2fc1f10afda7c7f5136fe7e668431b735f246a8ecd0e0ecbc39fc121496a31a4feb65cd618aaff9a993bcf99d7e21253af766be2255c7ae38365edb59ab155699016202a40331a7e5f3efa8552161534bd1430bdff1628083d091f8755e834dc869abc5697ae1c3edc6dfd75a85ed183f77b0749e3cb819ddc8975550274b267ffbfd0e2c17a948235f815e3154329e902391eab703f35eab756e398aeafb8419d757296600e6ef1f64601dd6907c6fece16c8221858dad70764f8d8fd5a8f031fc4167a1d6173ca99f415feb3ad26eb127667752503e245ff8247903b26b0000190de981c17a3fd9691a9e73777721b3c9818824378520c1088979a2e493a070998b7a988d2a58afb4273e43e3c33040c7eab4b2d4f28c164d31b2987b2e696a7e543f3468f1246ff2e50c95c5e353ce4c5f43c276c6d8099085131417cd3aa0be99a6f2b3429008a89ea75cd13dff6315080e0b2d38897bdaaf23b3a8d1194ef52fdc110aa0d18e5805126979e8e03dba6affb63ceb7532bfa99abc64b36ba7d71fed52a14cb5fd7ead8b1034195981dcbf039c8c91786f53b132929d79b8a379c8f0f9e4a55432cbbb546d8028d1ff9715db8ad0fc2ce510f24d0c99744297c5544b2d1dad0ef706cbb0b9023c0e28e057ef60ae0e25db530e1bd0de12e8db69d0b78c0579e2789756c88d6a60567750b0b80e0a2c6dc53ae7a002d612e589d068b11a17e1234cacfb34117e22eecc1695fc013d2919460ed5a64785a733d5f584775988c2aeada2ed3b0405d61b7189140f252cae3e4699a2b5b244eaa4fa454410899f46b6e594286d400a4d0e2adff96cf666f8ea43dbb7e9a16922dea32858396b7a270b9d9ee401c1df90676f1d1a92e23d50001613b6e6e048fd55a8c27d2ecdf29bade423614b86ce9fa74d63b9d369f0c6cb6e4e96fff3f954126d5a56719a6d497f1e8c816b4eda41d878ea6889682dd6e741cef545fd1a6677f9f94bafa6eb425e2a2c84c35afdaea590acb45f1cbe8dc73d05af78608ae81bea13efde522104245bd273729e93d650d1c3843e7011a25446d40f834ac32c7da33988291b343b510b5dd7ff1e3250b316e8e2be04839a728f471ce66602cd0b0e21a582e7b660680e2867fad602ba6cd4d7377104be911d62ed41a1152d9c6d636b37d84f4b3c6cac55ebc974fd1028ccd26905937d62eed6a41d0982258ace7d1c4f6794a49abfe48a4a3b949479bb8df918ba7f9c0054209d4c5eb12e827a44e7175d005fdbb20f83994f0832cddf77b41b8e4647bdd9fccb42580d333fe35403b282395b4fb400918da2176a84c6597871b847b1e3c957c714159f86ca6eced217416d692decfdb15a71e95e67e6d0c88c6928b88efd9b6995f758dff1bfd4385e408f912ef6e04806444e8a208e185e982ee2cbf0e2022242c5d5edc196bd5d1a915b8dfac356eeede65a3f724626a1b1765eef33dc63c180c4e6f44474b4fbf765ff3b3de7a3a63ea0304726b62e279bf981adefa08fce1a886fff9ab64c2019721fd3c2622f06256a41f8bb8d09cdedb776457f5c82446f20f14f1bf69f2df8dc3e42a380aab4e451a353d93726ba1920a632ea941339877ee7a2bb8f92ebf17719cb010b68217fe4ada5bb377997e6c8e5b39a847c13671f2fbbb9ad6bc1491af8b585d9c6af3618f7424d4c5ac7fba474ec3f96a2ab2b8a888cf133d85f8119cffce97ef020819c0b3750474788164c3ddb1a74711391e5e23b9a6552081f1b4f1f2e857d455e3919c97d18c58b49b7964dbc701183289c4cff593a69ce51c9b0aa4787750de5a6aed99ce677f9b78199bb5fc01b654c7bb6ea52a1d0940965c7300cafd103fc158a00b0b89fa54a314675c183cc18c412c69d03b2805849830f51b03aee3e2beb79af40601b2aedabc49609785d651c7b48efce8b45208cf3954d35d416b497a8f381366d4d6a1ee39173dcf936c2ae56332aeddefa2132493c66fce9dc7ddee01badd409e5808b9859b83186b0fcb2eeeec17ae5815bef17fc62ed87f05b859c6c433dd82774a1a2204da1f1b3c73a7f2775a94665bf43a445c716481a2e83e80c3975f0111af6b7a0a80c21e9d13a196839262ae542c84bcd2688b5a1074f665309973a693f1c76535d1765df98390a94fb45ebadb87e86511b01ab9b8ccd871b379a6314866d15becefd900169020ebba4729df1b9b10ea5f18b946a6dee6a27835f8da8d2a6a0c1dda4d199abdc43b47fd98cc35645545e827c494ad84ced17701667e2fbdef1b22036c7981daaf9877db22","scheme":"ml-dsa-65"} +{"id":"ml-dsa-65-nist-keygen-26","public":"36db0b5dce98bd190cb139e80b71b49c7d7040b71c5a1f3412c46bde939192b1b57ccb88ac2714c1240cb0eb62c689e031aea3d9f3eb3ed7bfa45931d288dcae3413199b31a7032560dce8a61e195d13a1440615c2f3aa7dd28c5b1b742bfa400052186721f13d3df9dcfaee348b10d66913c7148913e085e1a4a03c659398dadc6a8e0e0c1a7f9f44d30436db90fd65a6ab8f36137338255653baae8da21526a333426dbd9f76cce0f43212643e854d772018b35ce726bcaaa5ab0651baf8c122e13929bb35b6e4963df2595fdc7237cdaa7234bf776b07f353ccdba12ad3e025138e3492d7f8e929db55dc23e23075f66d57a10492e6a10ae7b758acc2291ca18ba1ca07a5b574ab6d8aac18b9524990ad2f110225b7d82f696300a660a166ad35b3c57ecbab77117c79656fa8ae2a19a7defb2afd2af54683d043be0f933b8eae0d591448ed55d00068cd9fe10b067fcfaac53aedb1e9b667e36c4e30231f85c7aa0a474af2fa4776226f4479555e155528d78b98183cbdf7fae4e7301140f163eb71e991d15fad4a0d2f25a5a62fa2e9bcc823cc2927662e40c538213ded9e2df508e911e4924e507a50861fbb050edbbf56d937206f8fbc6f4cead4cd10d06b73aadcd4aa39703a7a2bffae68b7baa47341b699da9f3b167d4d90efee0a07ee3529a3b5e8648b9cb07ee973e1d8dccf1d16e95092c4a0184ccb4902d6086d9f444aca5fa45f43ca91b351e82585989ffcbd6d2c3471d6b8593aa46f29d0dd9b44e8aa4d8f9a0bc886bb7982c56aab11e23bfdbd8bc674732fadacacae25fa416b2d0cc7743827293336507da4b14c1f0aa2e929af975466dadc89a016f33a0cca2d5c08114cf04b02358805a772536432c44dbe9886130d2d3a0ffa0e175875a2207686f5e562b879eb2957573ab706b942468c20cc69bc566d29d9f151f3cfae71cc97ce4a30722d4679fc1c089b5009935931ee60aac5496b0fd5f24e514c0e20fa1dcc7729184a50fc85fad1d2f32f715fbf55666e49f5a19761f2dd1aa5d1a33c7916eb6a794981c0334176abc493ef30d9eaeaad42e705989dcfcdeb578529a700bd14076a348a2062d6483cc63cd7f55136587aac0e531a06eb2de74e61cfcbbce18f2ada5a741f683bf101f71432ee659dd1508e0c8fb2400e0ccbe435da3466d543d3ef5ba369e125c0b84d855efe6d4a22ff929a7a7a984e448d23871e09b88a0bc3f3b7da55dd2edfb5a6daa102819ff50cd4dccd0a95d2f27354668065d4a56c31fb18b92b2a8db2c6453baa9333aea6eabb1bd6411d584dd5900262057a707f81cc5137dbdd9ac1079bb98da78a8e4bd1b2e0546c2b3d956fcc280d37d855e31f1e4315b387a742280f057f3219eae512884ae7ec4d2e3a72265b1d0163fbcbf616b2e289b0eaf9c63437d50b7b50ce408f5b4562f2abf510c19f5e8a0ace264db6e0f2a69a7d0b4a5e62a2b964f08c8ffe9c295f5773bdd7fab054a13822d428fae28ae5e4adc9d9f6e4dffc457a3e49f0bcf62b32961c4667b60960452afd917fdd00d954fa30c8533e5629f90af85948dc1bad889f91832ddf9b738254c9e7939726c37ab4557c2ce363c1391816c467537b471e5985e8084c277b62be514922d352e20689eabb3eb91c343f36e77b152d5e85afd088f4d02e7024b248a7420f58c7ebbeb480cae39b56164f5acd37a4f56b3db6e1cc6b7c8c96cd3c44a69d9ac99175257bab7fd83c5b574b5c9702c0fd13a5b176c60f82d2dfff50c2af25d96e0f8d27ec818d499e479b9642aed4a4a0e6af5f14cc5e1299eabae055ef3c763d1e350e2d76e92cee47a4233368466a298afb4ca108a325d2a4f8b79f21ee7349c1c186ecd7897f9886cf27ec01b05388870484867f84bae2c016d04a3762241907c4de207798dd125a2cebb6c2982f779e04117bdd65cd7ff0361a59d3ec05f6d903b6d15554beefb6d40d96a0d4b37ae76c69c1b9592088b7db878f95abedcb5fd5423ed93df1b27d01a4dc9f4438e7c55f35b0aeb7395b08e1ecbf15cb2b61d043c0454aeaef2d487093fa0d7de3fc6caf084b6a0f15a5cb05d9340d4e6763983dc45b7828539c77a60d5e081a03fe29949d916392b6d989b4c8c047e3635a76ba88ac18a7a18ccff5c7e06b02a43d2dff169fa449739e382bd020e0963c14a9acae6b6561c722d2bda183f33ee6a904df0207f5b098e56335cc063f9640c4997f593218d502f6b382354c73979e93c4b1b2471965ffa5a0dc8ee8eca9f5697e7ef08dc0eefd9ad75cd4122194b450201dfd73cda46a7b2478df66129fbb9c75b774213f9615bd990f8d07501fed440fd25d6cb912b8ecfa678d887a4ee28677e6e0491d49efc7a3b34b9815c5c22983da280d0afde2324f5281bc8b796ddacfd82723bbd9aa34b0c96075b36848591e47b80086897846fa76d092bc8bc6200837bfb5545039f8602b7ea49f63c0c3b8317eeeb7612f8e818dde09e43c7da76fd2ff6847906a45da3d993e8eaed9fb3b1e579d8cc6900c89522aaeb0b4a80da1e66ab8dfd62dfe4e4d77a3a77e5bd669207c70aa8537dd6d80a647b0420d79531a7456052c3c989f0f08de3d343c40067680b39ece95a17aac8a622d1d5d95b38ca0f11d94e5b0a7634eef4055517ace79f0df1d7c172e0246abb2ab6b135ee1a38a3b84f86fd7c3caf178cd4446d0b554256ad45c657e1192070aba7df480f489ebdf9753a79ccbc6aa893913c5f1271f1c6035","seed":"a991fd42b071d49c48ae3e75c647459e0daad1e1ba356a04801912d3294bcff8"} +{"id":"ml-dsa-65-sign-empty","message":"","public":"2841528a95e5cda35d99bc8d797774b577b254ca0680de5a07b0fdb75869b5a6a5b9f6e02cd0300fa485623ecc20ee4708a3d93fb4297a4fec246e170c6a5840b1dd6b6f01f138aa8045223d07a3ec11811f562fca76d59feb7a099015e9671acbbecab98c60cc8d1ea6aec39e54079504d970969ae75f028ee17678a528c3e245b2ab08fa54a3ab0f02d73d75c4911fc55c090086699fdc8a4dcd521dfbdc29e484534a9c0ac13984524aa714038d88bcdabb878785d3e7574d74be4339b44ce6c97bf1324a1053c30d1b5a8c1c84dd5d9b94cf7fd0c7e9310d57f0def75377d2ccbacf9c27b06ed27655f7203a16ec5d7995d9b9c202ea436100db185f9b9c4c64f310d177b12ddf5341afd5fa30d1601aff49e21640b99fbc36e6571e55d90d852fe59f7f3de92e8d3104cdeb6cb3b1451e7ea9efc341a0d090dc508bfce5fc2fc1f10afda7c7f5136fe7e668431b735f246a8ecd0e0ecbc39fc121496a31a4feb65cd618aaff9a993bcf99d7e21253af766be2255c7ae38365edb59ab155699016202a40331a7e5f3efa8552161534bd1430bdff1628083d091f8755e834dc869abc5697ae1c3edc6dfd75a85ed183f77b0749e3cb819ddc8975550274b267ffbfd0e2c17a948235f815e3154329e902391eab703f35eab756e398aeafb8419d757296600e6ef1f64601dd6907c6fece16c8221858dad70764f8d8fd5a8f031fc4167a1d6173ca99f415feb3ad26eb127667752503e245ff8247903b26b0000190de981c17a3fd9691a9e73777721b3c9818824378520c1088979a2e493a070998b7a988d2a58afb4273e43e3c33040c7eab4b2d4f28c164d31b2987b2e696a7e543f3468f1246ff2e50c95c5e353ce4c5f43c276c6d8099085131417cd3aa0be99a6f2b3429008a89ea75cd13dff6315080e0b2d38897bdaaf23b3a8d1194ef52fdc110aa0d18e5805126979e8e03dba6affb63ceb7532bfa99abc64b36ba7d71fed52a14cb5fd7ead8b1034195981dcbf039c8c91786f53b132929d79b8a379c8f0f9e4a55432cbbb546d8028d1ff9715db8ad0fc2ce510f24d0c99744297c5544b2d1dad0ef706cbb0b9023c0e28e057ef60ae0e25db530e1bd0de12e8db69d0b78c0579e2789756c88d6a60567750b0b80e0a2c6dc53ae7a002d612e589d068b11a17e1234cacfb34117e22eecc1695fc013d2919460ed5a64785a733d5f584775988c2aeada2ed3b0405d61b7189140f252cae3e4699a2b5b244eaa4fa454410899f46b6e594286d400a4d0e2adff96cf666f8ea43dbb7e9a16922dea32858396b7a270b9d9ee401c1df90676f1d1a92e23d50001613b6e6e048fd55a8c27d2ecdf29bade423614b86ce9fa74d63b9d369f0c6cb6e4e96fff3f954126d5a56719a6d497f1e8c816b4eda41d878ea6889682dd6e741cef545fd1a6677f9f94bafa6eb425e2a2c84c35afdaea590acb45f1cbe8dc73d05af78608ae81bea13efde522104245bd273729e93d650d1c3843e7011a25446d40f834ac32c7da33988291b343b510b5dd7ff1e3250b316e8e2be04839a728f471ce66602cd0b0e21a582e7b660680e2867fad602ba6cd4d7377104be911d62ed41a1152d9c6d636b37d84f4b3c6cac55ebc974fd1028ccd26905937d62eed6a41d0982258ace7d1c4f6794a49abfe48a4a3b949479bb8df918ba7f9c0054209d4c5eb12e827a44e7175d005fdbb20f83994f0832cddf77b41b8e4647bdd9fccb42580d333fe35403b282395b4fb400918da2176a84c6597871b847b1e3c957c714159f86ca6eced217416d692decfdb15a71e95e67e6d0c88c6928b88efd9b6995f758dff1bfd4385e408f912ef6e04806444e8a208e185e982ee2cbf0e2022242c5d5edc196bd5d1a915b8dfac356eeede65a3f724626a1b1765eef33dc63c180c4e6f44474b4fbf765ff3b3de7a3a63ea0304726b62e279bf981adefa08fce1a886fff9ab64c2019721fd3c2622f06256a41f8bb8d09cdedb776457f5c82446f20f14f1bf69f2df8dc3e42a380aab4e451a353d93726ba1920a632ea941339877ee7a2bb8f92ebf17719cb010b68217fe4ada5bb377997e6c8e5b39a847c13671f2fbbb9ad6bc1491af8b585d9c6af3618f7424d4c5ac7fba474ec3f96a2ab2b8a888cf133d85f8119cffce97ef020819c0b3750474788164c3ddb1a74711391e5e23b9a6552081f1b4f1f2e857d455e3919c97d18c58b49b7964dbc701183289c4cff593a69ce51c9b0aa4787750de5a6aed99ce677f9b78199bb5fc01b654c7bb6ea52a1d0940965c7300cafd103fc158a00b0b89fa54a314675c183cc18c412c69d03b2805849830f51b03aee3e2beb79af40601b2aedabc49609785d651c7b48efce8b45208cf3954d35d416b497a8f381366d4d6a1ee39173dcf936c2ae56332aeddefa2132493c66fce9dc7ddee01badd409e5808b9859b83186b0fcb2eeeec17ae5815bef17fc62ed87f05b859c6c433dd82774a1a2204da1f1b3c73a7f2775a94665bf43a445c716481a2e83e80c3975f0111af6b7a0a80c21e9d13a196839262ae542c84bcd2688b5a1074f665309973a693f1c76535d1765df98390a94fb45ebadb87e86511b01ab9b8ccd871b379a6314866d15becefd900169020ebba4729df1b9b10ea5f18b946a6dee6a27835f8da8d2a6a0c1dda4d199abdc43b47fd98cc35645545e827c494ad84ced17701667e2fbdef1b22036c7981daaf9877db22","seed":"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60","signature":"1437049a0204569bffab45670ce5106cbe9bef73c8db27d5a734005ff79d9cab306270ffa510bfb7c71ca3f74a98a336e3b98d690501164f7a5e67c41b497b0592a727ebfae69d7e89b303266d4e35cb583277d8b9793b2fa88ed8a3cfaaeb12ddee4eb90ad703a8b7eba2d9756b6b2b932062111319a392ee606fedaaf60644008a4b247b69d10ce5983c186cb113d0fc1b9466279d0e5814ec4c1584c4e6918b8b6f99d463f78503cf0cd35ffbe32885efc077cd3097b432dcbcae3848c7bda4c41f6a6f097104f46501faa2a0692612e950f20f349fe071d834b2807914638bc33fb123cd0c56ae2e2001fc4b7c2dbebbaff52cc9fe883ade549425ba0e08c69246a784e6c71483f5f954a0c4bf4818569afa921b1019d983e2f929d2b4f79b5e08b7dca7508c8c4d32866f93c77eadeca0d6c300118441e2c76630f6e81e205c4852dc8504e71d71a7e7566fd898180d201bffbb0d593787bfb928b02c53c7d4255c708f4c52787b18c403d87ce8813e1b80ca76ca00dee932e69f8cd2b8fc5ec37c21de3d327076b7e38fb017dd4878269d78ba831b2453f402b21000be7208d7d90deee91ef6248d4797babf58e7339fbbbb3d2716f7dafdbc0d9c0b7075f1db4773d7f93c47e5e95bf988cf10605ad0e58f709dadfcb9a0ace88700cc944100c7d6e3e49f3d9badd68b46208f34810c74fb23c91302d6616fbdfc551193f4d2c37412d394e279960a0ddf0db7b15d601b80d44e6169dc9db4095e794bd2c566301e97e4e2d6648aa120fe44362d891d59f24b56536cc75af735a8280432347cea646eeb516fd84208756f772a47908002c5604de626f52b055e368b3b065db5cb36fcb0ef694f354e5f47079e3f53af537fd7984aa43d7cef5ed59e8b5bd26730a046ad1a0d867731697e7e26d2128e543f051125c1f0ba8a109eebe4e17f27784a5014a8398bc3105f63bae2dbfc030f7ea6718453683721493c6939d5b8ac164493f11357ce7e8ba58a8a5358a1b73137858a02e97bcd12a30c72ad1e854057f24c586feffd3ae231aaf31a2939efc38ae4359cec293a28dae7d83584960268ab028ae2a7e93d91ebebb20e9cd71cf2f723057bb7ba897a800bffb8d450750b54bdfc0961d8e626dfcff88a2bb6083a893f0250d75754895ef021cf3c4e5666413a9f9ea4914a2925b1d912588f823ae5cd42384a1de3d3871779a57c2c9d3a8c84b4eb8523b627218e71d09d2c229505bd00b234491810ebdf29c94f31e7e948083c3c593fc79347021e878fbfe04dc57777235864af54991c0fff3124aa959b03fd8c5e1dd2755d9f3b678418518af22db312ad7ce3a642df4ba2d061b65a22c9519e0cc9febd762bd3faeb766301f162069c2b4f0b2668997b49752a2aba948e508263552fdf3b4cceda5cc7aa12fda36398dad1d43b6340444863205b7076ea77dec49686ecd244f17a8885c9f4f1942301f2f683c08a349a16a000c5039fd340bdad389018267abcba45fd24c355d90a80c1ace53b16208b7f7c4f47af373a0afdb2a422589f4e0908342ee8a14b8d04338c3f33105e0e2f74b33af39fb16487f6b8c75cab27b16acf6b9ad22fb3fb82a1dbdd011623e68c1d5696209ab934ede427f9b570a4bf1004c5377d87d7641ad673a4f4bb631a43b8045e01c7ffd57054ae7a6c5a2f1599b70cc232ead087a831b7437dd2cd7197e14e1319e9efe24420347809c881d5d2938e4fc7889dc60177e24cf7d19c7363b74ec36dfa493c6b8eafc02a443527b5bd4a03ee974f778f157deff8ea1f2f2d4396211e79073bfc82298d6bb6ea35647a0c0eee73642675b073548fe672985a64f447100600f47785df7cd9b15396dce4229a8f9a6f8af7caed2a33f6e20110d84aa81e43b11dc9e75c819c6af7609d72877d9c3638afaf4769eb82572c4fdfb3a290901da89cea51559f8f24bd40272cdd315249c08809d0ccf96d07124c9efc45abe5ca35b540859110cadb4509a81521c1703fa2b4cda4b5931fb8533e20c1f00ad9545892cb532d4358d1f1049187338f7e6d44da426ca7e7d84a2919ff62b73b4b43c4d2790d50ac455e1b40395d1ed7879373dc4d2676e0549385542c7ffb24b89f93d582d7cc6dc0287314b860e7c89d55fe993ee64ab99891a184aad2f7d75247d49a96eafa088e91a8fd96303a8f349b0c976f9ff534d38bd0f9f93424d66cf7054b4001bb606876785b4b99a89f52e7dd5690c74a6b4440aec16f4b598fd77362bc5e0955b4a66383eb6d06d1fbe586928d463c2a21b1fbf0cebe936aca03a0f12c85365bd9b865628bca23e3ec5ba0652be04a3527c7d8be2ccd3fdc66a53b1deb4f4875c3cd9fbf27959288ea025d5b401920e6b84550a2fd4ae5f515c4461e3625355146ee5f965c21b293c71c10b50558230061ddaf5a89f1c8be8d1e045d94608d9a644bb9a1a0de2db984865d57e2387f62163f9c5d33d59995a11fb6f5b8cd4b3e30c608a83d80903e8a5378bea2d5614bfc929ec0ad1ddc54c28bafcca0c474e802abf74c2587248b32b4b0a2f1d6f0f607750d7c7d7ede4632cdee0a74603043df10fce2d7d49ef54dedff4f259d1181d9099bc27d8defdb684caac6cdafc21535a1dd2d5577a3b35fe39807fe61366bf267e570614dd65d104e68c8a3d0d6134e23380b77d4858841b5e83751292fbb4e654e548e5fbbc25b6b7e8a298ffbb291b25dbc18c1e7d0f190b29abbe594cc0f216206a833a5ab178880313f6eab45aca60b84f6763a1a187a2b18720144ab19a5456d631281955039a72aa40779836b4ea0c2d93067ec1a5f41689557cc71169915a7626ca8ded41cf975a6ac70d7fca0392f061b508db52ec198742be4ebc36ada764df932dd224d470ee23a788d4d61dec0cbf3246ed36114605b19e86ea1262a8d8cfee3fc9b1c8d57bdcbc4c4e00b0ae902993151afa85b1c6aed47bc9e2f9220d09201cba73e9f15a5a670cffa2d2e19bc0bd097e45703522a7f190310051dd147916b6e9f2b414d80c0f2075ecd1bf2d5dfb7ef685e023366ebb55e14aba2c4284be29d04b017fd0d8c97bc064ca7d36aa2c0ba7aa9675b7876bb2a2fed7eec47fd88b96f80940aca9b18156b34748728edca2a32f8ba3eb5130bc7358d2c3b1a1b6edcb504044930090cbad65fa571b2f856a0ca4ffe3bc5f7f2d4077a24f8c56379b32cb00378beec412b314e4829c2bf412fa3e420b004905a3fce956acc2eb78cd7d75ffbed51d5abe8e9176aad9643261d4329c6b6425dc46bf5ae20afd1b046ba6caefb13212eaf900fc3c8a160d90fa9d906a771ebbac01537b6cf2c9e7266ca2a6406ee65c87ff120325eb502ea7a8e7e530a75fa8614d3d9f5563adb088a56b885938462b0605cca923ba4ba95c957adb35bf9b52c5caf25022171dbc8a0da2ceaf8aa18c689f3d3c4f5cbc62efbb24e899e5937c0d2f04e635b906269794311ab0915553a3ebdb27672214a63c6166f558e17f21d50c4e3cb3502134416280b58e1ed3ce96324b4ad5d7605c87a51e9559e02bd5bc3d490d7671399930c4ccc56a42c5618ef5de38356b907d4d9de0feddebf4e3c1692091ebb63361ed99d47a06c1173d623ee4c708f767ff36a6c238aab6ae963b8d8cb92a43b1ec2bd3a9c053bb30ff1dbeab3c4ee01080dd27866a7d6ccb4a4bd05c0e6ebd04b1edb2654ea56567c8c1da8e891255ae8e3eea95e0f04544234833115622e176b1af8ef594a53051e2013243cba334dd013b823209fb75121e746874aaae5747d6c5f64f3854ab8e69b39247b5a435c612f1b23fe523a56789901e67bd3e2c98249eda293d7e8d4fc89c8cc3e71503179ea1ca064bac5629b7483208a3df1bb2800528a6ac1d430e832665db3716dec62e0d3445a7b334d09cb03668177b6d4abfc4241e38935755db8699203b1a6e32b3b680642d27316288fffe607b64b69842012b265990c99fc836daf7840d329a405c9e2b9fc20a6a37e98f6468716557adc86dd471ec4124683c3c961b1e26c8a7a63e40829ff023b0ee050a19f1c90c0e9d326216c2eca8423d409bd5a1823416e32e540bc04bbd0b6287b7581ecf96b4fbc9f87c3e06edc19dccd22ef5aff5993973105e7507c34210caace6190e199b50ceeea18a200911ddc62e2e4948f001be2392fc56e2f1583c1082a7dff91715594015ecd8427669fe630768cd8d5a110efe4921bdb8d05a55f30b29bc853d5f74d6f1dcc2d06638b17677d810bc52d56f1ec37ad0b479d4f54af5d78cacc0988521aa5b2f6efbbba0cc53b26318b1f8ae1fb1700f760b8adc9432979ca7c521780da13748997cc20b9d5935ec3c57d5104be411a4124bf946c2cd6951fdcd4e328cf41148937badbc670141cea9b36d3e4fd2c657d0adc9b6437f882fc30c0b530b75dd6487ce98641e18d1931bb98506c4cc6f011dcf33904a21973be2dbdb7027d43ea386f50742cead9eb3a54616afeee67064912f13872b28e2a51de5e8d4e89a6fcc1d60029395e77e3d0be16e771ea1e824c6312cd18156482f88c086731b41ad95f0c3f71167f35f5f192108ab73b84b0b3b8c7e1e5f42d3b8db5cdfc2b3e545e9cf20d346c101b4c5e888dd2fbfd4a5f8388000000000000000000000000000000000000090f15182125"} diff --git a/vectors/spotcheck.jsonl b/vectors/spotcheck.jsonl new file mode 100644 index 0000000..54063ce --- /dev/null +++ b/vectors/spotcheck.jsonl @@ -0,0 +1,7 @@ +{"beta":"124417f3bbb8fcfaca31a6f3eb5c230a78db44a22502411f245d9fd088d911843d9efb674ffcf29df1cd0f0d8ea6d944bc37d765d45aed9fd64ebe7edc650784","checker_public":"rkzxigjCXg869PGSFAVr4EDXXRmwk+S/+wJ93lrG4dc=","id":"q1","minimum":10,"n":23,"rate":"0.05","receipt":{"at":"2026-10-11T15:02:11Z","by":"ana","doc":"hale2026harmonic-damb","evidence":[{"kind":"crop","node":"avbhhey","sha256":"942c23ea73a297e69c2ae8a82abe88d688de2532cb3f6d3543d1107c54f65b2e"},{"kind":"crop","node":"b5gd0h1","sha256":"a0b6f761fe95f8f29ef6dc37901fa85c7a62857b50b0163ca67b0aab048e4d17"},{"kind":"crop","node":"bnyvykm","sha256":"2c560caeaf914f3521fd0e3fca433922fcb9408c184c9b72bcfa869adf5ed409"},{"kind":"crop","node":"c20cna6","sha256":"bdbf7a4d9e86609675e3fc124c21ce808053a52d6bc0f35b15e1ba39027f13af"},{"kind":"crop","node":"d1mhw8b","sha256":"3104c57d9f8fb38302b057ead3bc44456da94f7c17d7c5c8f6db8732d4812c31"},{"kind":"crop","node":"ec5jc93","sha256":"321a926653b9e097987d255d9286880893d71abf895d73f1649403ed9ac0877d"},{"kind":"crop","node":"exms5gc","sha256":"cfc0e42e734470df5cfb741f92080526ef796bf48bcf05847d44f7091cfaaab1"},{"kind":"crop","node":"ganq1ns","sha256":"81d88697cd002fdfd770ee11413c550e4e4ffaa464d35841648311f278fc13bc"},{"kind":"crop","node":"hca6dc5","sha256":"a26619c3a9824bc19fddcf89ee618d9a4792d69110439f121eb717b6f98e88a6"},{"kind":"crop","node":"j6y45v6","sha256":"e689deda15dde9ad24433eb946200417473d273a1bf3136df67bf572256a483f"},{"kind":"crop","node":"jv1741a","sha256":"de60579bacfab769f614fa74d26d20c7b1aa02caf60af1479dc46b98ddcbc106"},{"kind":"crop","node":"k6a6616","sha256":"37b29d7ba293b27f913868690a785591d89ba9a4f47da8adaf764a4d5ae9675b"},{"kind":"crop","node":"m1p1n2g","sha256":"369c69758d2d09cc3d42b2424723c4fbc75f9ceb6817da81ce183be7d36f045f"},{"kind":"crop","node":"rr20tev","sha256":"f57e2cfe704d52c712b01e993e492b121ffe8c4d0174b11a0b0fa21fc5b9930b"},{"kind":"crop","node":"ryhrskg","sha256":"e6f816d93cfff8418dbb771ba03a09fb89a3b2438f97fabfc4ebef7f78af0dbf"},{"kind":"crop","node":"tkxsmts","sha256":"5d8e205660c2c59dcaff119b5671ac11650974b5287d7d7b239a9118e9171a85"},{"kind":"crop","node":"vd76637","sha256":"389742a44f1291e2dc7d7a69acd09410c92ed8a305718b2ab86b0b09b23253f4"},{"kind":"crop","node":"w0gr97q","sha256":"588a38407463e5674714899e6cf359810ccfed98fefdd2c1a90e8cb2ed0a9d64"},{"kind":"crop","node":"w264b74","sha256":"0babb0cef51933b8744f5b22d075069d51e431d3bdc08cb5e35d7822097b5953"},{"kind":"crop","node":"x3ns64d","sha256":"6bd7423a5933eb89572ded1d40d2f5baf6f6fa2f3c46791de8210f201a94b9d1"},{"kind":"crop","node":"ycwgbx1","sha256":"5ee72aca6b32e45f961f9cb2ff70408e71fc9ed7fccd28e91eb86e872041fed3"},{"kind":"crop","node":"yvkd7xr","sha256":"62fd5beecb3e76f430dfd142f443158b84657196af17173a976345a0cdd74449"},{"kind":"crop","node":"ztww0g8","sha256":"902e8ca35e1a313a81130c4c100aeb2233fd53854677b3a992fb16f744fe3151"},{"kind":"witness","sha256":"23b6b2aaece9cb0a828a2f0265539500fcf34d5195bf720b934b8bfdeccb9834"}],"format":"scienting-receipt/1","id":"y2zw8ctg5s8dp","level":"F3","nodes":[["avbhhey","c51730c0b1d7e11b51b317163ae42838f1be808b3690f196923482c9021f97c0"],["b5gd0h1","9635a750ac2acf526a4db28746fd3ed84659f4e384f5a73fef85d002b4e9308b"],["bnyvykm","13b0c5e01b52e467de5975acc898c2387fcc015d222517a865810a330a336c94"],["c20cna6","c8e6a553f5ae1377776e86dde6ee7d48a923dea7de417408841ea33b81563272"],["d1mhw8b","557a47334329925d191e772172fddbc1bd1a035eb2217240c476ee6bc43c92ab"],["ec5jc93","5421e9cf0ef3a995792963d0371b79e11a8efad519b02efb5cb88311a896d0cc"],["exms5gc","b7c47f8360eb7272d2ac0943e8bf1aec9d71cb4ea4e5e1d02f8acee5b430a038"],["ganq1ns","40d46db2088057debc3b1d5b4a3c972ff3a94fc3d5463565f98876d0927f1e67"],["hca6dc5","8cfed5a34aab28517e89e8a164f0f96c14361de83ebc800439116e83ef479f34"],["j6y45v6","00c4b92e220303ebc2bfb36aa557ac80ae4dba1675e9ed47adb82f6aeff10634"],["jv1741a","f644190803b5ea36aa24738e7f168a7fdf0d05cb5123c14a814b7628dab71f1e"],["k6a6616","90aa63a43587bdcee8e428c7dc7a95ac1502bdbcb9f49cae05c433db6d18348b"],["m1p1n2g","0847b5d75c2259257c3619e761c64d5571d3ca3932e96a96ee07e8ce68cc63be"],["rr20tev","76e06b4811a688357ac4b912172283463cfaf1b7a1f0795d274fc733a2309ba7"],["ryhrskg","525583990e7871a2ba55739e8206abac2df0f19d30c86ad74f6cafdd7c3cbe25"],["tkxsmts","cc0bf73dd84e298da0d36c4b363c8d2bdc9b6d5738d1923d14c4a9028dca08d6"],["vd76637","33810e4da42f8e65a224b5369c06fe8db254890294b7b6760808fe6e039da21a"],["w0gr97q","f738a008336ac59b2f1d45cda2f045dc96d34f0f1378c431ce6ff8e434feb8a7"],["w264b74","2ba9cea0f5c07ee9f7b47c5d541c85e92465709322869fb6c0d994ab61c56cad"],["x3ns64d","6bfc0a055148d877dbaf28b7f62565de7b6926137bf032c382282c39a4876797"],["ycwgbx1","167d1551ca64cad5b1143431c5af6d3fc24530887470b7fd265df88d1f54f267"],["yvkd7xr","aab8791a24bc4067c7e37fc5f0244d2128205e0a169e65c2c0fad977aabce313"],["ztww0g8","bda85639faacb77e504c891c035012602836171c009ecfd21584de4d6461ba93"]],"rev":12,"root":"373a7d860a14b58e5bfa9b9ad3bc916091bcb6db7556f0dbc9c71972a612494d","scope":"targeted:lode","signature":{"key":"ana","scheme":"ed25519","value":"2sraHCMlItocGta02EhvPlDW+F8rB1ZYMXBzA5lmNmtH0h+AlrNOPTbtykVSAWQXfKT2DXuB81/6x5jyNsIVBA=="}},"sample":["bnyvykm","c20cna6","d1mhw8b","exms5gc","ganq1ns","m1p1n2g","ryhrskg","w264b74","yvkd7xr","ztww0g8"],"seed":"3vORmZaL4zpWgtbZM29fKrWxgKOHhtXspIkutCyqgZgWUaBvmYCQfHtmCID+YNW2M+LIr8uMlpq/LD5cIp0omQRDdKSTIdrxoCxQHFgcwg0=","seed_payload":"{\"format\":\"scienting-spot-check/1\",\"receipt\":\"ae17f8866a05ca1b671d96b7758984e11ac694acd6743835f107cb513c7cc600\"}","size":10} +{"id":"size-3","minimum":10,"n":3,"rate":"0.05","size":3} +{"id":"size-10","minimum":10,"n":10,"rate":"0.05","size":10} +{"id":"size-199","minimum":10,"n":199,"rate":"0.05","size":10} +{"id":"size-200","minimum":10,"n":200,"rate":"0.05","size":10} +{"id":"size-201","minimum":10,"n":201,"rate":"0.05","size":11} +{"id":"size-3000","minimum":10,"n":3000,"rate":"0.05","size":150} diff --git a/vectors/targets.jsonl b/vectors/targets.jsonl new file mode 100644 index 0000000..3334bc0 --- /dev/null +++ b/vectors/targets.jsonl @@ -0,0 +1,3 @@ +{"anchored":["b5gd0h1","bnyvykm","c20cna6","exms5gc","ganq1ns","j6y45v6","jv1741a","m1p1n2g","rr20tev","ryhrskg","rzxn46v","w0gr97q","w264b74","ztww0g8"],"digit_rule":"all","expect":{"nodes":[["v3063qv","digits"],["rr20tev","anchored"],["tkxsmts","equation"],["hca6dc5","digits"],["ec5jc93","digits"],["xjns57z","digits"],["c20cna6","anchored"],["ztww0g8","anchored"],["j6y45v6","anchored"],["bnyvykm","anchored"],["w0gr97q","anchored"],["b5gd0h1","anchored"],["w264b74","anchored"],["exms5gc","anchored"],["jv1741a","anchored"],["m1p1n2g","anchored"],["ganq1ns","anchored"],["ryhrskg","anchored"]]},"id":"hale-all","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchored":["b5gd0h1","bnyvykm","c20cna6","exms5gc","ganq1ns","j6y45v6","jv1741a","m1p1n2g","rr20tev","ryhrskg","rzxn46v","w0gr97q","w264b74","ztww0g8"],"digit_rule":"anchored-sections","expect":{"nodes":[["rr20tev","anchored"],["tkxsmts","equation"],["hca6dc5","digits"],["ec5jc93","digits"],["xjns57z","digits"],["c20cna6","anchored"],["ztww0g8","anchored"],["j6y45v6","anchored"],["bnyvykm","anchored"],["w0gr97q","anchored"],["b5gd0h1","anchored"],["w264b74","anchored"],["exms5gc","anchored"],["jv1741a","anchored"],["m1p1n2g","anchored"],["ganq1ns","anchored"],["ryhrskg","anchored"]]},"id":"hale-anchored-sections","package":"fixtures/packages/hale2026harmonic-damb"} +{"anchored":["b5gd0h1","bnyvykm","c20cna6","exms5gc","ganq1ns","j6y45v6","jv1741a","m1p1n2g","rr20tev","ryhrskg","rzxn46v","w0gr97q","w264b74","ztww0g8"],"digit_rule":"none","expect":{"nodes":[["rr20tev","anchored"],["tkxsmts","equation"],["c20cna6","anchored"],["ztww0g8","anchored"],["j6y45v6","anchored"],["bnyvykm","anchored"],["w0gr97q","anchored"],["b5gd0h1","anchored"],["w264b74","anchored"],["exms5gc","anchored"],["jv1741a","anchored"],["m1p1n2g","anchored"],["ganq1ns","anchored"],["ryhrskg","anchored"]]},"id":"hale-none","package":"fixtures/packages/hale2026harmonic-damb"} diff --git a/vectors/vrf.jsonl b/vectors/vrf.jsonl new file mode 100644 index 0000000..280b26d --- /dev/null +++ b/vectors/vrf.jsonl @@ -0,0 +1,6 @@ +{"alpha":"","beta":"90cf1df3b703cce59e2a35b925d411164068269d7b2d29f3301c03dd757876ff66b71dda49d2de59d03450451af026798e8f81cd2e333de5cdf4f3e140fdd8ae","id":"rfc9381-example-16","proof":"8657106690b5526245a92b003bb079ccd1a92130477671f6fc01ad16f26f723f26f8a57ccaed74ee1b190bed1f479d9727d2d0f9b005a6e456a35d4fb0daab1268a1b0db10836d9826a528ca76567805","public":"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a","secret":"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"} +{"alpha":"72","beta":"8541f3ff9e0837a8a3c2b6da4326f0431a22bc7353edfedbc15089cab85bd4cb8108cbaf1e931fe2e6f477bb21a7bcdfe1c422c1ff2394b41379f4723ceb6b64","id":"rfc9381-key-alpha-72","proof":"cb809f3db77e2a15b9470e7b4cccb28ba08099a442bd357889505d3a5753143038392e8c6ec61b1796930d37bc58cbb5891b4d570a2180b3b18724ef9760bfffd4789004c970c70bd816cc104e9a110f","public":"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a","secret":"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"} +{"alpha":"af82","beta":"9df8bd916435e1a2ec0185aa3fe11396f9cfcb6966d72bc50a24beaa6e2cc40fb91dc7f5959874a3d6165be18f675f783525d8c32e6488456152d5f9bfc15b46","id":"rfc9381-key-alpha-af82","proof":"06eecb68db258fdd7161d2ca4a85fa59eef631fd60ee546c4cf53b03541a4416ab41be1cc4c3aa0877c2d5c856b4f606f0d7d478818d305c499e60e37b8d9644a58c7b677bff66ed1562b79e3f688204","public":"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a","secret":"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"} +{"alpha":"7b22666f726d6174223a22736369656e74696e672d73706f742d636865636b2f31222c2272656365697074223a2261653137663838363661303563613162363731643936623737353839383465313161633639346163643637343338333566313037636235313363376363363030227d","beta":"124417f3bbb8fcfaca31a6f3eb5c230a78db44a22502411f245d9fd088d911843d9efb674ffcf29df1cd0f0d8ea6d944bc37d765d45aed9fd64ebe7edc650784","id":"ben-spot-seed-q1","proof":"def39199968be33a5682d6d9336f5f2ab5b180a38786d5eca4892eb42caa81981651a06f9980907c7b660880fe60d5b633e2c8afcb8c969abf2c3e5c229d2899044374a49321daf1a02c501c581cc20d","public":"ae4cf18a08c25e0f3af4f19214056be040d75d19b093e4bffb027dde5ac6e1d7"} +{"alpha":"7b22666f726d6174223a22736369656e74696e672d73706f742d636865636b2f31222c2272656365697074223a2261653137663838363661303563613162363731643936623737353839383465313161633639346163643637343338333566313037636235313363376363363030227d","beta":null,"id":"tampered-challenge","proof":"def39199968be33a5682d6d9336f5f2ab5b180a38786d5eca4892eb42caa81981651a06f9980907c7a660880fe60d5b633e2c8afcb8c969abf2c3e5c229d2899044374a49321daf1a02c501c581cc20d","public":"ae4cf18a08c25e0f3af4f19214056be040d75d19b093e4bffb027dde5ac6e1d7"} +{"alpha":"7b22666f726d6174223a22736369656e74696e672d73706f742d636865636b2f31222c2272656365697074223a2261653137663838363661303563613162363731643936623737353839383465313161633639346163643637343338333566313037636235313363376363363030227d78","beta":null,"id":"other-input","proof":"def39199968be33a5682d6d9336f5f2ab5b180a38786d5eca4892eb42caa81981651a06f9980907c7b660880fe60d5b633e2c8afcb8c969abf2c3e5c229d2899044374a49321daf1a02c501c581cc20d","public":"ae4cf18a08c25e0f3af4f19214056be040d75d19b093e4bffb027dde5ac6e1d7"}