paperspec0.1.0

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#

opFieldsDoesIDs
replacetarget, find, replace, optional runReplaces 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.
insertparent, place_after (a sibling, or null for first), nodeAdds a subtree: kinds, labels, attributes and content, with each equation run naming its child as {"kind": "equation", "child": i}.New IDs, minted (4.2).
inserttarget, run, offset, textInserts text into one run of the target, at a code-point offset in that run's editable string.Unchanged.
deletetargetRemoves an artifact and its subtree, such as a running head read as text.All retired, without successors.
splittarget, offsetSplits 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.
mergetarget, with, optional joinerJoins 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.
movetarget, parent, place_afterChanges reading order or containment.Unchanged.
reclassifytarget, kindChanges a node's kind, such as a paragraph that is really a caption, to a kind with the same content shape.Unchanged.
relabeltarget, labelChanges a printed label.Unchanged.
settarget, attr, valueSets 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. Runs are made canonical after every operation, and the result MUST satisfy every rule of 3.

11.2 Every correction records#

PropertyHolds
evidenceAt 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).
reason, atWhy, 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:

PropertyHolds
index, idIts position, and its record ID.
before, afterThe target's node_hash before and after, or null; for an inserted subtree, target is its root.
pathThe target's ancestors when it was applied, root first; for an insert, the new subtree's.
to_pathFor a move, the new ancestors.
touchedThe 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, retiredIDs minted or retired.
fromThe 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) 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), 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.

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 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.

Source: spec/11-corrections.md · raw