Repository navigation
docs(adjudication): fix the anchor grammar and six 0003 details - #43
Merged
Merged
Conversation
Add an addendum to 0003 recording the owner's decisions on seven details SPEC.md §12 listed as left open by it, and move each into §11 as normative text: - a record's anchor is one frontmatter line holding a JSON object in one canonical form, with fixed key order and string escaping; `reply-to` is its own line; anything else is record-inconsistent - a referrer's pins are one canonical JSON object per line under `pins:`, sorted by path - a table's text joins cells by ` | ` and rows by `\n`, with a cell's `|` written `\|` so the string stays unambiguous - the leftmost of several longest chains is taken - thresholds compare as cross-multiplied integer inequalities - a short prefix or suffix must sit at the leaf's edge - a transclusion path resolves from the referrer's directory; an absolute path or one escaping the repository is unresolvable-path, a missing file document-missing The questions these raise are listed as new open items in §12. Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
List, in 0003's addendum, the precision choices the owner ratified beyond the seven rulings: canonical JSON, the record line set, the reply's lines, the pin block's rules, the table escape, the unresolvable-path reason and the current-index tie-break, each with its reason. SPEC.md's status paragraph now cites the addendum. Also decide that a ` - ` line after the pins end, across only blank, indented or comment lines, refuses the referrer's transclusions, and that a transclusion path is raw text for both resolution and pins. §12 now asks whether later versions admit further record keys or decode paths, rather than listing what §11 already decides. Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
This was referenced Oct 16, 2026
CameronBrooks11
added a commit
that referenced
this pull request
Oct 16, 2026
The reference resolver for `SPEC.md` §11, together with §11's conformance cases. The cases are #46's, `test/anchor-cases` at `d389dee` (215 anchor cases, 452 in all), written from `SPEC.md` by an author who had not read the resolver, and merged here with no case changed. Merging this lands both, and #46 closes as landed through it. `main`, with 0003's three addenda (#43, #47, #48), is merged in too. **Landing order** (decided). The first anchor case would turn the required `reference` check red on `main`, since the reader had no `resolve` until this PR. So the cases were written blind from `main` on their own branch and reviewed there, then merged into this branch and run against it. `README.md`, `AGENTS.md` and `SPEC.md` now say that the 0001 and 0002 cases came before the reader, and the 0003 cases after the resolver. ## Against the cases $ just conform # after merging d389dee, before any change made for it 0 failure(s) across 452 case(s) in the fixture tree $ just conform # at the head of this branch 0 failure(s) across 452 case(s) in the fixture tree No case failed, here or at the earlier merges of `e0f5525` (422 cases) and `7375c2c` (446). So no case is wrong per SPEC, no SPEC question came out of a failure, and the resolver needed no fix for the cases. `run_cases.MIN_CASES` is 452. ## What this adds `reference/blockspec/anchor.py`, standard library only, implements §11 on top of the existing reader: - **records** (§11.1): the exact frontmatter lines, the canonical JSON anchor (key order, spacing, escape set, `B` as 40 or 64 lower-case hex digits by object format, `N` as plain decimal), `replace` tied to `kind`, ULID file names and `reply-to`, a body the profile refuses, and the consistency rules against `base`, with occurrences counted by start position; - **correspondence** (§11.3): the leftmost longest chain, the §11.2 LCS alignment inside each gap with MOVED leaves left out, and EDITED pairing with the integer comparisons of the first addendum (`22/30 − 42/72` is tested as exactly 0.15); - **the anchored leaf** (§11.4): every rule and reason, in first-applies order; - **the span** (§11.5): hits counted by start position, the edge rule and the alignment check; - **input problems** in §11.10's order, replies included (third addendum); - **statuses, the suggestion gate and write-back** (§11.6, §11.7): NFC-to-raw mapping through container prefixes, lost indentation, CRLF and bare CR; a `\n` in `replace` written as the line's ending plus its container prefixes; and `unmappable-offset` for a span that does not map, for a line break that cannot be re-emitted, for a span crossing or ending right before a tab's leftover spaces, and for a span ending with a code block's final `\n`; - **transclusion** (§11.9): the pins grammar, path resolution, and steps 0 to 4, with a referrer the profile refuses reported as `"REFUSED(not-in-profile)"` and the first pinned leaf in the pinned blob's document order deciding among several `pinned-<reason>`s. `document.py` gains `resolve(repo, queries)`, the interface the runner calls. It loads `anchor.py` from its own directory by path and hands it this file's reader, so a mutated copy of the reader is the one the resolver runs. The reader's own output is unchanged: a script run locally compared `conform()` from `origin/main` and from this branch, messages included, for every `parse` case input, and got `237 inputs, 0 differ`. A copy with one line changed gives `237 inputs, 35 differ`. ## Fixed after review - A JSON array where the grammar wants an object (`anchor: [1]`, a leaf or a pin that is an array) raised out of `resolve()`. Objects are now told from arrays, and every malformed record or pin is `record-inconsistent`. The review's fuzz (6,000 random records, pins and referrers) now raises nothing. - `[a [b](c.md) d](policy.md#scram "transclude")` was read as a transclusion. Link text cannot hold a link (CommonMark 0.31.2, example 518), so it is no link and no transclusion. - The self-transclusion walk skipped a whole document when one of its paragraphs was undecided, so A to B to A went unseen. It now skips only that paragraph. - The claim that "moved leaves stay in gaps" is equivalent was false: with twins beside a move, the mutant swaps `repeat` and `unaccounted-copy`. It is an ordinary mutant now, a unit test kills it, and `anchor/repeat/twins-beside-a-move` kills it in the gate. - Shapes CommonMark decides, which were `UNDECIDED`: an image titled `transclude` is no link; a paragraph with no inline link is no transclusion; a title may be followed by a line ending before `)`; an entity reference is decoded only with its `;`, so `transclude` is not `transclude`. ## The mutation gate `just mutants` gates the resolver as well as the reader: a second table in `conformance/mutants.py` over `reference/blockspec/anchor.py`, probed by the whole tree. Its probe writes each mutant as `anchor.py` beside a copy of the reader. Mutants that only turn an `UNDECIDED` into a guess are left out, since no case can expect one, as are the duplicate-id warning and a notes-directory subfolder, which no case field can observe. The resolver's table, as the gate printed it: --- the resolver, reference/blockspec/anchor.py killed escape set misses U+2028 (1 case(s): anchor/record/accepts-every-escape) killed escape set misses C1 controls (2 case(s): anchor/record/accepts-an-escaped-c1-control, anchor/record/refuses-a-raw-c1-control) killed negative nth read (1 case(s): anchor/record/refuses-a-negative-nth) killed replace not tied to kind (2 case(s): anchor/record/refuses-a-suggestion-without-replace, anchor/record/refuses-replace-on-a-comment) killed canonical bytes not compared (7 case(s): anchor/order/grammar-before-document-missing, anchor/record/refuses-a-raw-c1-control, anchor/record/refuses-a-short-tab-escape) killed table pipe not escaped (1 case(s): anchor/leaf/an-escaped-pipe-keeps-two-tables-apart) killed heading level dropped (2 case(s): anchor/status/edited-when-a-heading-changes-level, anchor/suggestion/applies-when-a-heading-changes-level) killed text not normalised (3 case(s): anchor/status/resolved-when-the-normalisation-form-changes, anchor/suggestion/stale-when-the-span-does-not-map, anchor/suggestion/writes-back-without-normalising) killed half compares strictly (2 case(s): anchor/correspondence/a-similarity-of-exactly-one-half-pairs, anchor/near-copy/exact-with-an-unmatched-leaf-at-one-half) killed below one allows one (1 case(s): anchor/near-copy/an-exact-copy-elsewhere-is-not-a-near-copy) killed margin compares strictly (1 case(s): anchor/correspondence/a-margin-of-exactly-0-15-pairs) killed margin in floating point (1 case(s): anchor/correspondence/a-margin-of-exactly-0-15-pairs) killed alignment skips the second first (1 case(s): anchor/correspondence/the-gap-alignment-skips-the-base-leaf-first) killed chain is the rightmost (1 case(s): anchor/correspondence/a-swap-keeps-the-leaf-now-first-on-the-chain) killed chain is not the longest (55 case(s): anchor/correspondence/a-swap-keeps-the-leaf-now-first-on-the-chain, anchor/correspondence/the-gap-alignment-skips-the-base-leaf-first, anchor/exact-copy/a-paired-twin-does-not-count) killed moved pairs dropped (10 case(s): anchor/correspondence/a-swap-keeps-the-leaf-now-first-on-the-chain, anchor/near-copy/moved-with-its-reworded-text-in-place, anchor/refilled-gap/moved-with-a-new-leaf-in-its-place) killed moved leaves stay in gaps (1 case(s): anchor/repeat/twins-beside-a-move) killed no lcs in gaps (7 case(s): anchor/exact-copy/a-paired-twin-does-not-count, anchor/near-copy/an-exact-copy-elsewhere-is-not-a-near-copy, anchor/no-pair/a-twin-deleted-between-unique-neighbours) killed edit needs no half (2 case(s): anchor/correspondence/a-similarity-just-below-one-half-does-not-pair, anchor/status/orphaned-when-rewritten-beyond-recognition) killed edit needs no lead over other current (1 case(s): anchor/correspondence/the-margin-must-hold-on-the-base-leaf-side) killed edit needs no lead over other base (1 case(s): anchor/correspondence/a-margin-just-below-0-15-does-not-pair) killed no unaccounted-copy (3 case(s): anchor/no-pair/a-twin-deleted-between-unique-neighbours, anchor/repeat/one-of-two-adjacent-copies-deleted, anchor/repeat/twins-beside-a-move) killed repeat only when base repeats (1 case(s): anchor/repeat/a-copy-added-beside-the-leaf) killed repeat only when current repeats (2 case(s): anchor/repeat/one-of-two-adjacent-copies-deleted, anchor/repeat/twins-beside-a-move) killed exact near-copy off (3 case(s): anchor/near-copy/exact-with-an-unmatched-leaf-at-one-half, anchor/near-copy/exact-with-its-reworded-text-beside-it, anchor/suggestion/stale-on-a-refusal) killed near-copy below half (8 case(s): anchor/near-copy/exact-with-an-unmatched-leaf-just-below-one-half, anchor/pins/a-pin-matches-its-raw-path, anchor/refilled-gap/moved-with-a-new-leaf-in-its-place) killed exact near-copy counts exact copies (1 case(s): anchor/near-copy/an-exact-copy-elsewhere-is-not-a-near-copy) killed moved near-copy off (3 case(s): anchor/near-copy/moved-with-its-reworded-text-in-place, anchor/transclusion-order/a-pinned-reason-before-name-rebound, anchor/transclusion/pinned-near-copy) killed refilled gap off (1 case(s): anchor/refilled-gap/moved-with-a-new-leaf-in-its-place) killed exact-copy off (1 case(s): anchor/exact-copy/edited-with-its-old-text-unmatched) killed exact-copy counts paired copies (2 case(s): anchor/correspondence/the-gap-alignment-skips-the-base-leaf-first, anchor/exact-copy/a-paired-twin-does-not-count) killed crowded gap off (2 case(s): anchor/crowded-gap/edited-with-a-new-leaf-beside-it, anchor/transclusion/pinned-crowded-gap) killed edited near-copy off (1 case(s): anchor/near-copy/edited-with-a-variant-elsewhere) killed empty span allowed (1 case(s): anchor/record/refuses-an-empty-span) killed triple may occur twice (3 case(s): anchor/order/a-quote-twice-before-base-unavailable, anchor/record/refuses-a-quote-that-occurs-twice, anchor/record/refuses-a-quote-that-overlaps-itself) killed short prefix anywhere (1 case(s): anchor/record/refuses-a-short-prefix-away-from-the-edge) killed short suffix anywhere (2 case(s): anchor/order/a-short-context-before-base-unavailable, anchor/record/refuses-a-short-suffix-away-from-the-edge) killed occurrences skip overlaps (2 case(s): anchor/record/refuses-a-quote-that-overlaps-itself, anchor/span/overlapping-hits-are-ambiguous) killed no prefix edge rule (1 case(s): anchor/context/a-short-prefix-must-sit-at-the-leaf-start) killed no suffix edge rule (1 case(s): anchor/context/a-short-suffix-must-sit-at-the-leaf-end) killed two hits not ambiguous (2 case(s): anchor/span/overlapping-hits-are-ambiguous, anchor/span/two-hits-are-ambiguous) killed no alignment check (1 case(s): anchor/span/the-alignment-detaches-a-rewritten-span) killed gate ignores status (3 case(s): anchor/suggestion/stale-when-accepted, anchor/suggestion/stale-when-rejected, anchor/suggestion/stale-when-resolved) killed gate applies on moved (2 case(s): anchor/residual/r1-a-deleted-leaf-quoted-elsewhere, anchor/suggestion/stale-on-moved) killed break written as LF (2 case(s): anchor/suggestion/writes-a-line-break-as-a-bare-cr, anchor/suggestion/writes-a-line-break-as-crlf) killed break written with no prefix (2 case(s): anchor/suggestion/writes-back-in-a-block-quote, anchor/suggestion/writes-back-in-a-list-item-continuation-line) killed synthetic spaces mapped (1 case(s): anchor/suggestion/writes-back-a-span-beginning-after-leftover-tab-spaces) killed absolute path allowed (1 case(s): anchor/transclusion/unresolvable-path-with-a-scheme) killed scheme path allowed (2 case(s): anchor/transclusion-order/unresolvable-path-before-broken-pins, anchor/transclusion/unresolvable-absolute-path) killed above the root allowed (1 case(s): anchor/transclusion/unresolvable-path-above-the-root) killed pins order unchecked (4 case(s): anchor/pins/refuses-a-path-pinned-twice, anchor/pins/refuses-pins-out-of-order, anchor/transclusion-order/broken-pins-before-document-missing) killed pins after a blank line read (2 case(s): anchor/pins/refuses-a-pin-after-a-blank-line, anchor/pins/refuses-a-pin-after-a-comment-line) killed name ref skipped (1 case(s): anchor/transclusion/a-name-that-binds-nothing-now) killed rebound unchecked (3 case(s): anchor/pins/a-pin-matches-its-raw-path, anchor/transclusion/name-rebound-by-a-leaf-inserted-after-the-marker, anchor/transclusion/name-rebound-when-the-marker-moves) killed reply-to not canonical (1 case(s): anchor/reply/refuses-a-reply-to-with-extra-spacing) killed pin not canonical (1 case(s): anchor/pins/refuses-a-pin-not-in-canonical-form) killed pins line with trailing text (1 case(s): anchor/pins/refuses-a-pins-line-with-more-after-it) killed dot segment kept (2 case(s): anchor/pins/a-pin-matches-its-raw-path, anchor/transclusion/resolves-relative-paths-from-a-subdirectory) killed synthetic char inside span mapped (1 case(s): anchor/suggestion/unmappable-span-across-a-tab-left-by-fence-indentation) killed repeat ignores counts (3 case(s): anchor/repeat/a-copy-added-beside-the-leaf, anchor/repeat/one-of-two-adjacent-copies-deleted, anchor/repeat/twins-beside-a-move) killed over-long context read (2 case(s): anchor/record/refuses-a-prefix-longer-than-32, anchor/record/refuses-a-suffix-longer-than-32) killed reply-to any string (3 case(s): anchor/reply/a-malformed-reply-to-before-document-missing, anchor/reply/refuses-a-lower-case-reply-to, anchor/reply/refuses-a-reply-to-that-is-not-a-ulid) killed lowercase ulid read (1 case(s): anchor/record/refuses-a-lower-case-ulid-file-name) killed reply parent never found (3 case(s): anchor/reply/a-reply-to-a-record-renders, anchor/reply/a-reply-to-a-reply-renders, anchor/reply/a-reply-to-an-orphaned-record-renders) killed base checked before record-only checks (2 case(s): anchor/order/a-quote-twice-before-base-unavailable, anchor/order/a-short-context-before-base-unavailable) killed record body not checked (1 case(s): anchor/record/refuses-a-body-the-profile-refuses) killed document missing ignored for records (3 case(s): anchor/input/document-missing, anchor/input/document-renamed-without-its-notes, anchor/order/document-missing-before-base-unavailable) killed base read before the document (1 case(s): anchor/order/current-not-in-profile-before-base-unavailable) killed lazy bq line repeats a shorter prefix (1 case(s): anchor/suggestion/unmappable-line-break-on-a-lazy-line) killed lazy list line repeats a shorter prefix (1 case(s): anchor/suggestion/unmappable-line-break-on-a-list-item-s-lazy-line) killed tab after a quote marker repeated (1 case(s): anchor/suggestion/unmappable-line-break-under-a-quote-marker-and-tab) equiv item first line repeated (a list item's first line holds its marker in the prefix region, so the lazy-line check refuses the break anyway) killed break with no ending written (1 case(s): anchor/suggestion/unmappable-line-break-on-a-last-line-with-no-ending) killed refused referrer enumerated (3 case(s): anchor/referrer/refused-for-a-conflict-line-in-a-fence, anchor/referrer/refused-for-conflicting-adjacent-re-pins, anchor/referrer/refused-for-raw-html) killed pins before the path (1 case(s): anchor/transclusion-order/unresolvable-path-before-broken-pins) killed broken pins ignored (9 case(s): anchor/pins/refuses-a-path-pinned-twice, anchor/pins/refuses-a-pin-after-a-blank-line, anchor/pins/refuses-a-pin-after-a-comment-line) killed missing target after the pin (1 case(s): anchor/transclusion-order/document-missing-before-base-unavailable) killed slug-only name not checked early (2 case(s): anchor/transclusion-order/a-slug-only-name-before-base-unavailable, anchor/transclusion-order/a-slug-only-name-before-the-pinned-binding) killed slug match ignored (2 case(s): anchor/transclusion-order/a-slug-only-name-before-base-unavailable, anchor/transclusion-order/a-slug-only-name-before-the-pinned-binding) killed marker name taken for slug-only (2 case(s): anchor/merge/re-pins-of-two-targets-merge-cleanly, anchor/transclusion/a-marker-name-that-is-also-a-slug-resolves) killed pinned blob not required (2 case(s): anchor/transclusion-order/an-unbound-name-after-base-unavailable, anchor/transclusion/base-unavailable) killed pinned name unchecked (1 case(s): anchor/transclusion/a-pinned-name-that-binds-nothing) killed orphaned pinned leaf passes (2 case(s): anchor/transclusion-order/several-pinned-reasons-report-the-first-leaf, anchor/transclusion/pinned-orphaned) killed last pinned leaf decides (1 case(s): anchor/transclusion-order/several-pinned-reasons-report-the-first-leaf) killed anchor array taken for an object (1 case(s): anchor/record/refuses-an-anchor-that-is-an-array) killed inner link ignored (1 case(s): anchor/transclusion/a-link-inside-link-text-is-not-one) killed entity without semicolon decoded (1 case(s): anchor/transclusion/an-entity-without-a-semicolon-is-not-decoded) killed image read as a link (1 case(s): anchor/transclusion/an-image-is-not-one) killed prose with a title read as a link (1 case(s): anchor/transclusion/prose-with-the-title-s-characters-is-not-one) killed line ending after the title refused (1 case(s): anchor/transclusion/a-line-ending-before-the-closing-parenthesis) killed code block's final line ending written (1 case(s): anchor/suggestion/unmappable-span-ending-in-a-code-block-s-final-line-ending) killed reply's document unchecked (3 case(s): anchor/reply/document-missing-before-a-missing-parent, anchor/reply/refused-when-its-document-is-missing, anchor/reply/refused-when-its-document-is-not-in-profile) 91 killed, 0 survived, 1 equivalent, 0 stale, 0 broken **No survivors.** The six holes the last run reported, one per review fix, are now killed by the cases #46 added for them. **One equivalence claim**, "item first line repeated": a list item's first line holds its marker in the prefix region, so the lazy-line check refuses a break there anyway. kindkit flags a claim only when the suite kills the mutant; it cannot show that one the suite does not kill is equivalent, so this rests on the argument. ## Where SPEC.md is still open: refused, not guessed Each of these returns `{"status": "UNDECIDED", "question": ...}` for that record or transclusion, which no case can expect. **Left open by §12:** 1. Transclusion shapes: a destination with no path, angle brackets, another title quoting form or a title with backslash escapes or entity references (one that decodes to `transclude` but is not written `"transclude"`), a `transclude` link in a paragraph that holds other text, a transclusion in a list item or block quote, no pin, and a document that transcludes itself, directly or through another. 2. Writing a suggestion back into a table. 3. An empty path segment, and a path naming a file that is not markdown (read here as not ending in `.md`). **Not in §12, and not decided either:** 4. A destination with no `#name`. 5. Link text holding a code span or HTML, either of which can move where the link text ends under CommonMark. 6. A line break written over a span whose first and last lines end or are prefixed differently: §11.7 writes each `\n` as the ending of "the line it breaks", and such a span has two candidates. 7. Where the open transclusion questions sit in step 1's order: the empty segment and self-transclusion after the path resolves, the non-markdown target before the pins, and no pin at step 1.6. 8. Inputs no case should produce: a record or referrer that is not in the tree, and a record path in no notes directory. **Cheap to decide but left `UNDECIDED`** (CommonMark settles them, at the cost of a full inline parser): prose that holds `"transclude")` alongside a real inline link elsewhere in the same paragraph. **Readings taken, not refused**, worth confirming: - When the span ends at a line break, write-back maps its end past the next line's prefixes, so `> a\n> b` with `a\n` replaced by `x` gives `> xb`. - A paragraph holding `"transclude")` in a link-like shape is treated as a possible transclusion and refused as undecided where it is not exactly one link. That refuses more than needed, and never resolves wrongly. ## Gates $ just check All checks passed! $ just test 181 passed in 13.02s $ just conform 0 failure(s) across 452 case(s) in the fixture tree $ just tree 452 cases: 160 accept, 77 refuse, 215 anchor 0 problem(s) $ just mutants --- the reader, reference/blockspec/document.py 91 killed, 0 survived, 0 equivalent, 0 stale, 0 broken --- the resolver, reference/blockspec/anchor.py 91 killed, 0 survived, 1 equivalent, 0 stale, 0 broken ## Break-checks of the unit tests `tests/test_anchor.py` was break-checked by a sweep run locally (not committed). It hashes the file before and after each mutation, reports BROKEN when one does not land, runs the tests, and restores the file. The latest run gave `105 killed, 1 not`, the one being the equivalent mutant above. The hook and the gate's scratch location: `3 killed, 0 not`. ## Not covered - The thresholds 0.5 and 0.15 are as §11 states them; nothing here measures them on real history (0003 §12). - Re-anchoring (§11.1) and the tool behaviours of §11.11 are not implemented: the format does not require them. --------- Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an addendum to
docs/adjudications/0003-anchors.mdrecording theowner's decisions of 2026-10-16 on seven details that
SPEC.md§12 listedunder Left open by 0003, and moves each into
SPEC.md§11 as normativetext. No implementation and no conformance cases change.
What the addendum decides
anchor: <json>,kind: …,status: …(orreply-to: "<id>",kind: commentfor a reply). The anchor is a JSON object (RFC 8259) in one canonical form: keysbase,leaf{type,nth,text},span,prefix,suffix, thenreplacefor a suggestion only;", "and": "spacing, nothing else;",\, LF escaped as\",\\,\n; U+0000–001F, U+007F–009F, U+2028, U+2029, U+FEFF, U+FFFE, U+FFFF as lower-case\uXXXX; nothing else escaped. Anything not byte-for-byte in that form, or any other frontmatter line, isrecord-inconsistentpins:, then one- {"path": P, "blob": B}line per target, same canonical form, sorted bypathby code point, no duplicates.pathis the destination's part before#, as written. A malformed pins block refuses every transclusion in the referrer asrecord-inconsistent\n, then NFC. The escape keeps two different tables from becoming copies4·L ≥ T,2·L < T, and40·L₁·T₂ − 40·L₂·T₁ ≥ 3·T₁·T₂for the 0.15 marginprefixorsuffixmust sit at the leaf's edge, or the occurrence is not a hit.dropped,..pops); a path starting with/or whose first segment holds:isunresolvable-path, as is a..above the repository root; a path naming no file isdocument-missingThe addendum also lists, as the owner's decisions on the precision, the
choices the seven rulings left to the write-up: byte-exact canonical JSON
(key order, spacing, escape set, 40/64-hex
base, plain-decimalnth),the exact record line set,
reply-toas a JSON string with a replycarrying
kind: commentand nostatus, the pin block's rules, the\|table escape,
unresolvable-path, and the tie-break by current indices(which differs from a base-order reading on a two-leaf swap). A transclusion
path is raw text, for resolution and for pins alike, and a
-line afterthe pins end, across only blank, indented or comment lines, refuses the
referrer's transclusions.
unresolvable-pathis a new resolution reason (§11.10). §12 drops the sixitems now decided, keeps the rest of the transclusion-details item, and
gains a list of new open items raised by these decisions.
Evidence for the claims in the text
JSON and YAML 1.1 read the same values. 20,000 random anchors, with
strings drawn from U+0000–00FF, U+2028, U+2029, U+FEFF, U+FFFE, U+FFFF,
a combining mark, an astral character and YAML punctuation, written in
the canonical form:
json.loadsand PyYAML 6.0.3safe_loadagreed onevery one, and none contained LF or CR. For YAML 1.2, an independent run
with js-yaml 4.2.0 and
yaml2.8.3 found 0 disagreements with JSON over20,000 anchors.
The integer forms. Checked against Python
Fractionon 200,000random draws with
Tup to 120: no disagreement. With floats,22/30 - 42/72evaluates to0.1499999999999999, so>= 0.15isFalsewhere the exact answer isTrue.Pin merges, git 2.47.3, stock
git mergeof two branches off one base:So one line per target does not by itself stop two added pins from
conflicting; the addendum says so, and sorting by
pathis what spreadsadditions apart. That a conflicted referrer is refused rests on the
suite's reading 12, which the addendum names as a reading.
The worked example in 0003 §3, rewritten canonically: its
prefixis 31 code points with the leaf's start 31 before the span, and its
suffixis 32.Checks
Not merged: this awaits review.