Files
paperspec/spec/11-corrections.md
T
alexm 62f54ed869
check / check (macos-latest) (push) Canceled after 0s
check / check (ubuntu-latest) (push) Canceled after 0s
Initial commit
2026-10-11 23:45:29 -04:00

5.7 KiB

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).
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 is an addition to the design's eight operations, needed to fix table structure; see DECISIONS.md. Runs are made canonical after every operation, and the result MUST satisfy every rule of 3.

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.
reason, at Why, and when.

A proposal, such as one an MCP client 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) 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. a target, parent or sibling is not live, or the root would be deleted, moved, merged or reclassified;
  2. find is empty or does not occur exactly once;
  3. an insert has no crop evidence;
  4. 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;
  5. any leaf outside touched has different digits afterwards;
  6. a split falls outside the sentence, inside a run other than text, or leaves a part empty;
  7. a merge joins nodes that differ in kind, are not mergeable, or are not adjacent siblings;
  8. a move would put a node inside itself;
  9. a reclassify changes the content shape, or a relabel or set targets a kind that does not take it; or
  10. the result breaks a rule of 3.

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.