diff --git a/docs/comprehension-history.md b/docs/comprehension-history.md index 8cc01fe..2d12b6c 100644 --- a/docs/comprehension-history.md +++ b/docs/comprehension-history.md @@ -1472,3 +1472,29 @@ Inherited architect, decided by: - Shape: `src/markdown/emit/inline-line.ts:247` `inlineRuns`. The base grew the previous run in place in one loop. The new version uses a `next` skip cursor, a helper that overshoots, and `inside.slice(0, holders)` to take back trailing spanned nodes; the rule is sound and a comment explains it, but it takes longer to verify. `RunGrouping` is satisfied structurally by passing the whole `InlineContext`. - Self-sufficiency: `spec/flavour.md:568` section Marks, read against `src/markdown/emit/inline-line.ts:115` `linePass` and `writesSpanned`. The spec says that where the spanned line does not read back "the run breaks there", while the code parts every run on the line. The code's test is "no fallback, and no directive in a flavour without directives", not a read-back to the same nodes, so a reader holding the spec is misled about which one applies. - Self-sufficiency: `src/markdown/mark-spellings.ts:49` `insideRun`. The base comment gave the footgun: the reducer must ask this grouping or it trims by runs the writers do not spell. The new comment is a bare spec pointer, and no comment on `runsSharedWithNext` carries that warning forward, so the reason the reducer imports the emitter's walk is unstated in the code. + +## 2026-11-03T22:54:25Z, PR #112 at 8e1ba5d, against 0166a71 + +Ruling: worse + +| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall | +|---|---|---|---|---|---| +| Mid A | better | worse | better | same | worse | +| Inherited architect | better | worse | better | same | worse | + +Mid A, decided by: + +- Locality: `src/markdown/emit/inline-line.ts:129` `takeFallback`. The first call ignores the fallback it was handed and only flips `parted`, so what a pass means now depends on hidden mutable state. `emitLine` (line 97) starts at pass 0 to compensate, and its comment has to explain why. At base (`src/markdown/emit/inline-line.ts:130`) each call did what its argument said. +- Locality: `src/markdown/portable/inline-reduction.ts:264` `judgedLine`. The reducer now mirrors the writer's spanned-then-parted order and judges two differently trimmed lines. It returns the parted `leaves` because the fallback's indexes only fit that line, so `spellableLine` and `withoutFallback` must keep the two paired. At base `spellableLine` (line 230) judged and fixed the one `current` line. +- Locality: `src/markdown/portable/inline-reduction.ts:202` `runsSharedWithNext`, read with `leafEdges` at line 222 and `edgeDepth` at line 241. Trimming a leaf's whitespace now needs a run walk over the whole line, delivered through an index-parallel `shared` array read as `shared[index - 1]` and `shared[index]`. At base `sharedRuns` (line 221) compared a leaf with its neighbour and could be read alone. The new way is the more honest source of truth, but the unit can't be understood without `inlineRuns`. +- Locality: `src/markdown/emit/inline-runs.ts:32` `inlineRuns`, read with `runEnd` at line 38. A run is now found by lookahead with an `end` skip, and crossed nodes keep their `outer` through `insideRun(...) ?? runNode`. So `outer` no longer tracks `depth` in `emitRun`, and `tryLink` must read `nodes[0]?.outer`. At base (`src/markdown/emit/inline-line.ts:232`) a run was built by appending to the previous one, and `outer` was always `depth + 1` inside a run. +- Navigation, Shape: `src/markdown/emit/inline-runs.ts:19` `inlineRuns`. Run grouping, `RunNode`, `insideRun` and `carries` now share one file named for what it holds, and writer and reducer both ask it. At base they were split between a private function in `inline-line.ts` and `mark-spellings.ts`, which held run concepts in a file about spellings, plus the reducer's own `sharedRuns`. +- Shape: `src/markdown/emit/line-escaping.ts:23` `MarkRun`. A run now names its `mark` where it named `depth`, a positional index into each node's marks. `withoutMarks` (`src/markdown/portable/inline-reduction.ts:294`) and `endsAlone` (`src/markdown/emit/unspellable-runs.ts:94`) therefore say which mark they mean, with no index to keep aligned. + +Inherited architect, decided by: + +- Locality, Overall: `src/markdown/emit/inline-line.ts:129` `takeFallback`: the first fallback it is handed is thrown away and only sets `parted`, so a reader must already know that a verdict on the spanned line says nothing about what the parted line needs. In 0166a71 each call took what it was given. The loop in `emitLine` now also starts at pass 0 (:97), and `readBackPasses` counts past it, which adds more order to keep in mind. +- Locality, Overall: `src/markdown/portable/inline-reduction.ts:264` `judgedLine`: it restates the writer's order, spanned then parted, outside the writer, and returns different leaves from the ones it received, so the two orders stay in step only by hand. `spellableLine` (:250) retries the spanned line on each pass while `emitLine` keeps `parted` set once flipped, an asymmetry the reader has to reconcile. In 0166a71 `spellableLine` made one fallback call on the current line. +- Locality: `src/markdown/portable/inline-reduction.ts:241` `edgeDepth`, with `runsSharedWithNext` (:202) and `countSharedRuns` (:209): in 0166a71 `sharedRuns` answered from a leaf and its neighbour alone. Now the number comes from a recursive walk of the whole line's runs, under a grouping threaded through `trimmedEdges`. Reading it as "outermost marks" rests on the invariant stated in the comment at `edgeDepth`. +- Navigation, Shape: `src/markdown/emit/inline-runs.ts:19` `inlineRuns`: "why did this run group so" now has one named file, shared by the writer and the reducer. In 0166a71 the grouping was private to `inline-line.ts`, and `insideRun` sat in `mark-spellings.ts`, a file about spellings. `inline-line.ts` is lighter for it, though `carries` at :61 stretches the new file's name a little. +- Shape: `src/markdown/emit/line-escaping.ts:23` `MarkRun`: it holds the mark itself where 0166a71 held a `depth` index, and that index would be wrong once a run crosses nodes. `withoutMarks` (`inline-reduction.ts:294`) and `endsAlone` (`unspellable-runs.ts:94`) now read as what they do. This outweighs a smaller cost: `depth` in `emitRun` and `outer` in `RunNode` now mean different things.