Skip to content

docs(adjudication): decide how anchors and transclusions resolve - #41

Merged
CameronBrooks11 merged 12 commits into
mainfrom
docs/adjudicate-anchors
Oct 16, 2026
Merged

CameronBrooks11 merged 12 commits into
mainfrom
docs/adjudicate-anchors

Conversation

@CameronBrooks11

@CameronBrooks11 CameronBrooks11 commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Adds docs/adjudications/0003-anchors.md, which decides how comments, suggestions and transclusions anchor to text in a blockspec document. The aim is that after edits and a stock git merge, an anchor either lands on the right text or is refused loudly. It also adds SPEC.md §11, which carries the resulting rules.

Stacked on #40, whose SPEC.md this extends. The base is docs/spec-draft-0, so the diff shows only this change.

No implementation and no conformance cases. The reference resolver and the cases come later, and the cases come first, from an author who has not read a resolver.

What 0003 decides

decided where
Q1 one record file per comment or suggestion, in <doc>.notes/ 0003 §2, SPEC §11.1
Q2 comments follow a moved leaf, marked MOVED; suggestions never apply to one 0003 §5–§6, SPEC §11.6–§11.7
Q3 an unreachable base is REFUSED(base-unavailable). Before landing, a tool MAY re-base each record that resolves onto the branch head. A CI check MAY require that; records that do not resolve keep their base, are reported, and do not fail the landing 0003 §1, SPEC §11.11
Q4 a transclusion is refused once its name is rebound, until the referrer re-pins 0003 §7, SPEC §11.9
Q5 transclusion is a titled link, [t](doc.md#name "transclude"), amending 0001 0003 §7, SPEC §4.2, §11.9
Q6 the refill rule is kept 0003 §4, SPEC §11.4
Q7 resolving through merge parents is a tool's option that only adds refusals, outside the format (Q9's identity tracking likewise; Q3's re-basing is not a refusal rule) 0003 §1, §9, SPEC §11.11
Q8 records are not deleted in normal use; a purge removes a whole thread; an orphaned reply is #REF!(reply-to) 0003 §2, SPEC §11.8
Q9 the notes directory is authoritative; a rename moves it in the same commit; a duplicate record id across directories is warned on; a tool MAY track document identity 0003 §2, SPEC §11.8, §11.11
Q10 only status: open suggestions apply 0003 §6, SPEC §11.7
Q11 write-back only through an exact NFC-to-raw mapping, else unmappable-offset 0003 §6, SPEC §11.7
Q12 the twin narrowing: only an unmatched exact copy refuses an edited leaf 0003 §4, SPEC §11.4
Q13 32-code-point context, no comment-only fallback, until a real-history replay 0003 §5, SPEC §11.5

0003 also fixes these details beyond the thirteen answers, and lists them under its decision table:

  • the resolution reasons and their names, including not-in-profile for any snapshot the profile refuses, and #REF!(name);
  • record-inconsistent for a short context away from the leaf's edge, for an empty span, and for a pinned name that binds nothing;
  • replace is written exactly as stored, never normalised.

It also covers:

  • the resolver's steps: correspondence (§4), then the span (§5);
  • the resolution reasons, listed in SPEC §11.10;
  • a table of the outcome each edit shape must produce (§8);
  • the residual (§9): four mechanisms whose bytes match a legitimate edit. R1 is a deletion plus a verbatim copy elsewhere. R2 is a rewrite beyond recognition with the old wording left in order. R3 is a sentence rewritten inside a leaf with the old one re-added in the same context. R4 is a different document at the same path. The section says which of them reach suggestions and what would close each.

spike/LOG.md §9 is cited as the published single-commit instance of that family.

No figure in 0003 measures these rules on real history. Its What would reverse it starts with that replay.

Outline

0003:

  1. what the format guarantees, and what it cannot
  2. where anchors live
  3. the record
  4. which leaf: correspondence and when to refuse
  5. which characters: the span, and statuses
  6. suggestions
  7. transclusion
  8. what each edit must produce
  9. the residual
  10. prior art
  11. the cost of reversing each choice
  12. what would reverse it

Then the effect on 0001 and 0002, and what draft 0 carries.

SPEC.md §11 has twelve subsections:

  1. records
  2. leaves, keys and similarity
  3. correspondence
  4. the anchored leaf
  5. the span
  6. statuses
  7. suggestions
  8. replies, deletion and document identity
  9. transclusion
  10. resolution reasons
  11. what a tool MAY add
  12. what this does not prevent

The former §11, Not decided, is now §12.

Also edited:

  • SPEC.md §4.2 names the one inline shape with meaning, and §8.3 says slugs are not transclusion targets
  • README.md and AGENTS.md list 0003 and say it has no cases yet
  • DESIGN-BRIEF.md §2 points its quote-anchoring question at 0003

Open questions 0003 leaves undecided

These are listed in SPEC.md §12:

  • the exact syntax of a record's frontmatter: which YAML, quoting, and where reply-to sits
  • how a referrer's pins are written in its frontmatter
  • a table leaf's leaf.text, since §6.3 gives a table's content as rows of cells
  • which chain to take when several are longest, which decides EXACT against MOVED
  • whether the 0.5 and 0.15 thresholds are compared exactly or in floating point
  • whether a hit must reach the leaf's edge when the stored context is short because the edge was nearer
  • transclusion details: how path resolves, a destination with no path, the title's other quoting forms, a transclude link among other text, a transclusion inside a container, a transclusion with no pin, and self-transclusion
  • what a validator reports for a rename that leaves its notes directory behind and for a duplicate record id, and whether either has an identifier
  • the thresholds themselves, which come from D8 and are untested for this resolver
  • range anchors, a selection across leaves, still open from 0002 §2

Checks

The case tree and the reference reader are unchanged. Nothing implements 0003 yet.

$ just check
All checks passed!
$ just conform
0 failure(s) across 237 case(s) in the fixture tree
$ just tree
0 problem(s)
$ just test
8 passed in 1.57s

Add SPEC.md: the CommonMark 0.31.2 block-level profile with GFM pipe
tables, frontmatter, blocks and leaves, region markers and what each
binds, name resolution and heading slugs, and the eleven refusals with
the identifiers the conformance suite compares, including the two
fixed orders between them.

The document adds no decision. It defers to the adjudications where
they disagree, and lists in its last section each question they leave
open, naming the suite reading that pins it where one does.

Point README.md, AGENTS.md and the case tree's README at it.

Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Add adjudication 0003. Comment and suggestion records live one per
file in <doc>.notes/. An anchor resolves from two snapshots, its base
blob and the current text, through leaf correspondence, near-copy,
refill, crowded-gap and twin rules, a 32-code-point context and a
character alignment, and is loud wherever those disagree. Comments
follow moves; only open suggestions apply, never on a moved leaf, and
only through an exact offset mapping. A transclusion is a paragraph
that is one link titled "transclude", pinned by the referrer and
refused once the name is rebound, which amends 0001.

The document names the four edit shapes the bytes cannot tell from
legitimate edits, and what a tool may add on top of the format.

Add SPEC.md section 11 with the rules and the resolution reasons, move
"not decided" to section 12 with what 0003 leaves open, and point the
README, AGENTS.md and the brief at it. No implementation and no cases.

Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Limit "only refuses more" to merge parents and document identity, and
describe re-basing before landing as what it is, with a CI check that
reports records that do not resolve instead of failing the landing.

Define write-back through the parse, so only the span's own text must
match after NFC. Refuse a short context away from the leaf's edge and
an empty span as record-inconsistent, write replace as stored, and
use not-in-profile for any snapshot the profile refuses. List the
details 0003 fixes beyond its thirteen answers, add #REF!(name) to
the reasons, and note that an insertion between a one-line marker and
its leaf rebinds the name.

Correct citations: 0002 §4 gives no syntax, the author-chosen name
comes from D8 §7.2 and §11, the thresholds are borrowed from difflib
ratios, and wrong_on_deleted counts wrong units.

Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Scope the ambiguous-table order to one table's lines, and the marker
indentation rule to where a block can start, marking each as a
reading of the addendum's wording. State that U+0000 becomes U+FFFD
per the pinned grammar, that UTF-8 is the brief's decision with no
refusal code yet, that a lazy delimiter line is paragraph text, and
that 0002's Decision text decides the general table rule.

List conflict markers inside a fence as reading 4 beside reading 12,
add the transclusion unit from 0002's Decision, and leave whether a
slug names a heading or its section undecided, as 0002 §4 does.

Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
The tree is already exempt from normalisation by .gitattributes.

Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Base automatically changed from docs/spec-draft-0 to main October 16, 2026 02:37
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Write each line break in a suggestion's replacement with the line's
own ending, say that a bare CR is the source of a content \n in a
bare-CR file, and point 0003's write-back bullet at the content-based
mapping in section 11.7. A lazy line that starts another block, such
as `- | -`, starts it; only other lazy lines are paragraph text. Call
a top-level indented marker in paragraph context a paragraph
continuation line.

Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
@CameronBrooks11
CameronBrooks11 merged commit 42b12fe into main Oct 16, 2026
6 checks passed
@CameronBrooks11
CameronBrooks11 deleted the docs/adjudicate-anchors branch October 16, 2026 02:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant