Files
paperspec/spec/18-layers.md
T
alexmandClaude 7890fa1ad7 feat: trace annotation body for traced citations; paperspec.traces
A trace follows one citation of a sentence of a citing paper to a passage of the
cited paper (spec/18 section 18.5). Minor change: a new body kind, optional
properties and two rules, with no valid file made invalid.

- annotation schema branch (source, selector, reference, note, verdict, proposer;
  proposer required for a Software creator); body_kind in sql/store.sql; the note
  and proposer terms of the JSON-LD context; rules layer.trace.source and
  layer.trace.target.
- paperspec.traces: resolve(annotation, citing_state, cited_state, same_as) gives
  current, changed, stale, unlinked or misresolved with open and cites; problems,
  disputes, disputed.
- fixtures/records/traces/ on writer2027fixed-ynr7.v3 and vectors/traces.jsonl
  (29 cases); check.py runs the record checks over both layers; counts, glossary,
  examples and CHANGELOG updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uy4ZYbWRoCdUtWLEfigysY
2026-10-17 20:12:04 -04:00

13 KiB

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, 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).
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).
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) 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, pin, role That the span states, uses or disputes a claim.
symbol SpecificResource source, pin, key, symbol That this occurrence of a symbol, the one whose key is key, is the symbol a symbol claim defines.
comment TextualBody category A remark, opinion or interpretation.
caveat TextualBody category A warning a reader should see.
question TextualBody for, category A question for a reader, a group or the authors.
exercise TextualBody exercise A task with a key and a rule (19).
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.
trace SpecificResource source, selector, reference, note, verdict, proposer That the target's sentence cites reference on the strength of a passage of the cited document (18.5).
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).

A textual body has a value, and optionally a format (text/plain or text/markdown) and a language.

The source of a claim-link or symbol body is a claim in a paperclaim claim store, written as paperclaim writes a reference: claim: and the claim's tag, eight Crockford base32 capitals (the digits and the letters without I, L, O and U), as in claim:272XTX7C, or claim:<host>/<tag> for a claim in another store, <host> being a domain name. A tag never changes, while a claim's slug, such as amber/k-bond, may be renamed, so a slug is never a reference. The optional pin fixes the claim as the annotator read it: the same reference, @, and the first six lowercase hex digits of the claim's statement hash, as in claim:272XTX7C@02f47b. common.schema.json defines both, as claimRef and claimPin.

A symbol body names its symbol twice, as the target's span and by key, the symbol's key in the math form scienting-math/1 (9.4), which a claim store gives the symbol a symbol claim defines: K_{r} for a span $K_r$. So a reader finds every occurrence of a symbol across a library by its key, however its source spaced or braced it, and a claim store matches the annotation to its claim without parsing the span. The span is still required, since the key says which symbol and the span says where; symbol, optional, is the symbol as the span writes it.

A comment, caveat or question body MAY carry a category, which says what it is about, from a fixed list:

category Says
comment A general remark.
context Background, related work, or what a reader should know to follow the span.
critique A flaw in the method, the analysis or the argument.
question A question.
correction An error of fact, number, citation or reference in the paper.
feedback A suggestion addressed to the authors.
resource Data, code or a related paper.

A producer that supports categories SHOULD set one on every comment, caveat and question; the property is optional only so that layers written before it stay valid. The category is independent of the kind, so a caveat may be a correction and a question a critique. A correction category says that a reader found an error in the paper; correcting the document's reading of it is a correction of 11. The store's annotations table keeps the category beside the body's kind (13.4). 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, each comment, caveat and question with its category, a claim link and a symbol that reference a paperclaim claim and pin it, and the receipt that confirms some of them.

18.5 Traced citations

"As previously reported [12]": a reader who finds where the cited paper reports it marks the passage, and the trace body keeps the mark. A crosslink says only that two spans correspond, in both directions, whereas a trace goes from one sentence's citation to one passage, and says which reference it follows, why, and who or what found it.

The annotation's target is a leaf or span anchor (6.4) on the citing sentence, which MUST be a leaf with runs, a sentence or a cell, and MUST cite the reference the body names: one of its cite runs lists reference (3.5). reference is the ID of a reference node of the citing document, because a sentence may cite several references at once, as in [3, 12], and the target says only which sentence. source is the cited document, written as a target's source is, tag:scient.ing,2026:doc:<store>/<key>, and never the citing document itself. selector selects the passage in it: an AnchorSelector whose anchor holds the passage's pin (its node_hash) and, for part of a leaf, its span, then a TextQuoteSelector when the anchor's quote is plain (18.3). The passage may be a container, such as a table, whose anchor has no quote.

Property Required Holds
reference Yes The reference node of the citing document that the sentence cites and the trace follows.
source, selector Yes The cited document and the passage in it.
note No What the passage reports, in a person's or a tool's words.
verdict No supports, partly, does-not or cannot-tell, as a citation-context body has it (19.2).
proposer When the creator is Software {model, run, score?, rank?}: the model and run that found the passage as a candidate, as a generated body's generator names them, the candidate's score as a decimal string, and its rank, from 1, among the candidates the run proposed for this citation.

The state of a trace is the annotation's status. A trace a tool proposes is proposed until a person confirms it, and rejected when a person turns the candidate down; a rejected candidate is kept, so that the tool is not offered it again. A trace is disputed while a reply to it, an annotation whose target is the trace and whose motivation is assessing, is proposed or confirmed. The dispute is computed from the replies and never written on the trace, so a reply can be withdrawn.

Whether a trace still leads where it did is also computed, from the current state of both documents. Resolve the target's anchor against the citing document and the body's anchor against the cited document (6.5). The first row that applies gives the outcome:

Outcome When
stale An anchor is stale, on the citing side, the cited side or both.
unlinked The sentence no longer cites reference: a relink removed the citation (11.7), or the reference was deleted.
misresolved A resolve made the reference name a DOI or a document that is not the cited work. A resolution of none names nothing and contradicts nothing (10).
changed Both anchors resolve and at least one is not current.
current Both anchors are current, and the reference still resolves to the cited work or to nothing.

A resolution names the cited work when its document is the cited document, another version of the same work (a key with the same work key, 2.4), or one the caller knows to be the work; and a doi resolution does when the work is known by that DOI (same_as, 2.4). Besides the outcome, a resolution gives the passage's current address, key#node@pin[start:end], while its anchor resolves, and the citations inside the passage. A chain of "as previously reported" is then followed one trace at a time: the reader opens the passage, and a citation in it that has a trace of its own leads on.

A trace breaks layer.trace.source when its selector has no AnchorSelector, an anchor is in another document than source names, source is the citing document, or the TextQuoteSelector does not repeat the anchor's plain quote. It breaks layer.trace.target when the target is not a leaf with runs of the citing document selected by an AnchorSelector, or the sentence does not cite reference (22.4). vectors/traces.jsonl resolves traces against the fixture packages after corrections, with every outcome and every refusal, and fixtures/records/traces/ holds a layer of four annotations on writer2027fixed-ynr7.v3 that cites hale2026harmonic-damb: a trace a model proposed to the paper's abstract and a person confirmed with a receipt, a candidate a person rejected, a person's trace to Table 1, and a reply that disputes the first.