141 KiB
Comprehension history
2026-10-09T00:41:03Z, PR #19 at 859c952, against 9519606
Ruling: better
| Seat | Vote |
|---|---|
| Mid A | better |
| Inherited architect | better |
Mid A, decided by:
src/markdown/portable/task-ids.ts:7mintTaskIds: one walk, no carried set filled by the parser as a side effectsrc/markdown/parse/markdown-to-adf.ts:26Reading: plain data,codeBlockNodeno longer mutatescarriedsrc/markdown/portable/conventions.ts:8flavourClaims: one table states what each reader claims; branches name the claim they testsrc/markdown/parse/markdown-to-adf.ts:161quoteNode: the title is read in the reader's own flavour, no hop throughinlineLeavessrc/index.ts:5exports: each call named by its flavour; "plain" no longer means two things
Inherited architect, decided by:
src/markdown/parse/markdown-to-adf.ts:26Reading: the hiddencarriedset and the retryingmintTaskIdsare gonesrc/markdown/parse/markdown-to-adf.ts:161quoteNode: parser and emitter no longer correct only togethersrc/markdown/parse/markdown-to-adf.ts:113readBlock: branches name the claim (claims.alerts,claims.taskMarkers)src/index.ts:5exports: flavour names say which file to opensrc/markdown/portable/conventions.ts:3flavourClaims: cost, all three flavours' rows live underportable/
2026-10-09T00:56:04Z, PR #19 at 5fc877e, against 9519606
Ruling: better
| Seat | Vote |
|---|---|
| Mid A | better |
| Inherited architect | better |
Mid A, decided by:
src/markdown/portable/conventions.ts:8flavourClaims: one table says what each flavour reads; every gate reads a named fieldsrc/markdown/portable/task-ids.ts:7mintTaskIds: one pass, no carried set crossing modulessrc/index.ts:5exports: each name says which markdown it meanssrc/markdown/parse/markdown-to-adf.ts:161quoteNode: no reach into the portable writer's reductionsrc/markdown/portable/conventions.ts:20ReadClaims: cost,directiveNodeleans on a type in another file
Inherited architect, decided by:
src/markdown/portable/task-ids.ts:6mintTaskIds: the retry loop and the parser-filled set are gonesrc/markdown/parse/markdown-to-adf.ts:26Reading: no hidden state; branches name the feature they gatesrc/markdown/portable/conventions.ts:8flavourClaims: cost, the table for all three flavours lives underportable/src/markdown/emit/line-escaping.ts:92escapeClaims: directive escaping under the flag the parser checkssrc/markdown/emit/adf-to-markdown.ts:146spellPortableBlock: no hard-coded lossless title
2026-10-09T01:43:11Z, PR #21 at c45320b, against 9a242c7
Ruling: better
| Seat | Vote |
|---|---|
| Mid A | better |
| Inherited architect | better |
Mid A, decided by:
src/markdown/parse/markdown-to-adf.ts:23MarkerParagraph: the block kind says a marker's paragraph holds no lone image, wherereadMarkedscanned its output afterwardssrc/markdown/emit/image.ts:7tryImage: builds what the reader would build and compares, whereimageShaperestated the shape by handsrc/markdown/parse/inline-content.ts:25InlineContent: one rule replaces five image refusal sites over two filessrc/markdown/external-image.ts:4centeredImage: one builder for the shape three literals heldsrc/markdown/parse/inline-content.ts:550pieceNodes: costs more — its image arm relies onassemblehaving linked every top-level image
Inherited architect, decided by:
src/markdown/external-image.ts:4centeredImage: the image's ADF shape is defined once for reader, emitter and portable reducersrc/markdown/parse/markdown-to-adf.ts:23MarkerParagraph: replacesreadMarked's after-the-fact search and its caller-computed flagsrc/result.ts:1ConvertErrorCode:unmappable-imageand its refusal paths are gonesrc/markdown/parse/inline-content.ts:43Image: costs more — four functions must agree on the image'slinksrc/markdown/parse/inline-content.ts:26InlineContent: costs more — no longer image xor nodes
2026-10-09T08:38:28Z, PR #21 at 1098b5e, against 9a242c7
Ruling: better
| Seat | Vote |
|---|---|
| Mid A | better |
| Inherited architect | better |
Mid A, decided by:
src/markdown/external-image.ts:4centeredImage: one builder where three places built the image node by handsrc/markdown/emit/image.ts:7tryImage: compares against what the reader builds, whereimageShaperestated the shapesrc/markdown/parse/markdown-to-adf.ts:26TaskParagraph: a named block kind replacesreadMarked's after-the-fact index searchsrc/markdown/parse/inline-content.ts:302assemble: costs more — which of three readings an image takes hangs on a one-line condition and theinLinkflagsrc/markdown/parse/inline-content.ts:26InlineContent: costs more — no longer image xor nodes
Inherited architect, decided by:
src/markdown/external-image.ts:4centeredImage: the image shape is defined once for reader and both writerssrc/markdown/emit/image.ts:7tryImage: the emitter cannot drift from the readersrc/markdown/parse/markdown-to-adf.ts:136readBlock: the task paragraph is routed where the block is classifiedsrc/markdown/parse/inline-content.ts:302assemble: costs more — the most expensive line to decodesrc/markdown/parse/markdown-to-adf.ts:154paragraphsOf: costs more — the name does not say it splits the marker line
2026-10-09T08:46:45Z, PR #21 at e7029c1, against 9a242c7
Ruling: better
| Seat | Vote |
|---|---|
| Mid A | better |
| Inherited architect | better |
Mid A, decided by:
src/markdown/emit/image.ts:7tryImage: builds what the reader would build and compares, whereimageShaperestated the shapesrc/markdown/external-image.ts:4centeredImage: the image shape lives in one named filesrc/markdown/parse/markdown-to-adf.ts:26TaskParagraph: a typed block kind replacesreadMarked's after-the-fact searchsrc/markdown/parse/inline-content.ts:302assemble: costs more — one dense ternary overinLinksrc/markdown/parse/inline-content.ts:26InlineContent: costs more — no longer a discriminated union
Inherited architect, decided by:
src/markdown/external-image.ts:4centeredImage: one builder where three had to stay in stepsrc/markdown/parse/markdown-to-adf.ts:136readBlock: the task paragraph is routed by a named block kindsrc/result.ts:1ConvertErrorCode: one rule no longer enforced at five sitessrc/markdown/parse/inline-content.ts:26InlineContent: costs more —contentNodedropsimagesilentlysrc/markdown/parse/inline-content.ts:302assemble: costs more — three routes from an image piece to text
2026-10-09T09:00:13Z, PR #22 at fe5c731, against 78655bc
Ruling: same
| Seat | Vote |
|---|---|
| Mid A | same |
| Inherited architect | same |
2026-10-09T09:52:41Z, PR #22 at 6f1a16b, against 78655bc
Ruling: worse
| Seat | Vote |
|---|---|
| Mid A | worse |
| Inherited architect | worse |
Mid A, decided by:
src/markdown/emit/inline-line.ts:106takeFallback: a range may part joined breaks or carry, decided by state an earlier pass builtsrc/markdown/emit/inline-line.ts:316emitMarkedRun: a carry that signals parting totakeFallbacktwo levels upsrc/markdown/emit/inline-line.ts:233joinsRun: a lookahead whose shortcut holds only byinlineRuns' call ordersrc/markdown/emit/inline-line.ts:58portableLineFallback: a second retry loop sharing the partingsrc/adf/inline-nodes.ts:5InlineNodeModel.marks: reads as "has marks", not "takes marks"src/markdown/parse/inline-content.ts:328linkTo: the comment hides that the breaks stay after the destination
Inherited architect, decided by:
src/markdown/emit/inline-line.ts:331emitMarkedRun: the newline check returns a carry that is a parting signal, one fact over three functionssrc/markdown/emit/inline-line.ts:106takeFallback: two growing sets whose order matterssrc/markdown/emit/inline-line.ts:58portableLineFallback: a second retry loop with its own exit rulesrc/markdown/emit/inline-line.ts:233joinsRun: lookahead, shortcut and three conditions per break;inlineRunstakes the whole contextsrc/adf/inline-nodes.ts:5InlineNodeModel.marks: the name hides "takes marks"src/markdown/parse/inline-content.ts:328linkTo: the comment no longer says an empty destination reads as nothing
2026-10-09T09:57:25Z, PR #22 at 45b5446, against 78655bc
Ruling: worse
| Seat | Vote |
|---|---|
| Mid A | worse |
| Inherited architect | worse |
Mid A, decided by:
src/markdown/emit/inline-line.ts:100takeFallback: the first fallback is discarded to stop joining, known only from a commentsrc/markdown/emit/inline-line.ts:200inlineRuns: an indexed loop moving its own counter byjoinedBreaks' resultsrc/markdown/emit/inline-line.ts:226joinedBreaks: six positional parameters and two jobs
Inherited architect, decided by:
src/markdown/emit/inline-line.ts:101takeFallback: a hidden first step that takes no fallbacksrc/markdown/emit/inline-line.ts:200inlineRuns: runs built by a forward scan the reader steps through by handsrc/markdown/emit/inline-line.ts:56portableLineFallback: checks an unjoined line while the final emit starts joinedsrc/markdown/emit/inline-line.ts:40LineFallbacks.joinsBreaks: a fallbacks field whose fallback value is false
2026-10-09T10:02:23Z, PR #22 at f195ebd, against 78655bc
Ruling: same
| Seat | Vote |
|---|---|
| Mid A | same |
| Inherited architect | same |
2026-10-09T10:07:15Z, PR #22 at 37629e4, against 78655bc
Ruling: same
| Seat | Vote |
|---|---|
| Mid A | same |
| Inherited architect | same |
2026-10-09T10:19:03Z, PR #22 at 239218f, against 78655bc
Ruling: same
| Seat | Vote |
|---|---|
| Mid A | same |
| Inherited architect | same |
2026-10-09T12:13:22Z, PR #24 at d109199, against 78655bc
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | same | same | better | better |
| Inherited architect | same | same | same | worse | same |
| Maintainability senior | same | better | worse | same | same |
| Junior A | better | better | same | same | better |
Mid A, decided by:
- Navigation, Self-sufficiency:
src/markdown/portable/task-list.ts:5splitTaskList: the split rule is one named unit both directions import, where it sat inbulletNodeandreduceTaskList/nestIn - Self-sufficiency, Navigation:
src/adf/inline-nodes.ts:12inlineNodes: "a hard break takes no marks" is the fieldtakesMarks: false, read by parser and emitter - Shape:
src/markdown/portable/adf-to-portable-markdown.ts:289reduceTaskList: the loop lost itsnestedaccumulator andnestIn; line 303 packs the split and a merge into one expression - Shape, Locality:
src/markdown/portable/task-list.ts:8splitTaskList: astandingflag across iterations andstandsoverwritten mid-iteration;heldTasksays little - Locality:
src/markdown/parse/markdown-to-adf.ts:86readBlocks:bulletNodereturns a schema-breaking task list that its caller splits, and neither says so - Self-sufficiency:
src/markdown/parse/inline-content.ts:328linkTo: the comment covers the hard-break case
Inherited architect, decided by:
- Self-sufficiency:
src/markdown/portable/task-list.ts:5splitTaskList: the comment states the schema constraint, not the rule; the loop must be traced by hand - Locality:
src/markdown/parse/markdown-to-adf.ts:201bulletNode: builds a schema-breaking intermediate that onlyreadBlocksrepairs under an unexplained guard - Locality:
src/markdown/portable/adf-to-portable-markdown.ts:311reduceTask: droppingblankedCoderests on a guarantee neither unit states - Locality:
src/markdown/portable/adf-to-portable-markdown.ts:317nestIn: two hand-mirrored halves of one rule became one function - Self-sufficiency, Locality:
src/adf/inline-nodes.ts:12inlineNodes:takesMarks: falsemakes the hard-break rule checkable at its source - Self-sufficiency:
src/markdown/portable/adf-to-portable-markdown.ts:288reduceTaskList: the comment no longer prepares the reader for line 303 - Shape:
src/markdown/portable/task-list.ts:12splitTaskList:standing/standsreuse a wordreduceStandinguses for another meaning
Maintainability senior, decided by:
- Locality:
src/markdown/portable/task-list.ts:5splitTaskList: the stay-or-stand rule lives once, where the reader'sbulletNodeand the writer'snestInmirrored it - Locality:
src/markdown/parse/markdown-to-adf.ts:86readBlocks:bulletNodereturns a shape the caller quietly replaces, behind an unexplainedblock.kindguard - Shape:
src/markdown/portable/task-list.ts:9splitTaskList: two cross-iteration accumulators, a negated compound ternary, near-synonym names, andheldTaskhides the taskItem conversion - Shape:
src/markdown/portable/adf-to-portable-markdown.ts:303reduceTaskList: one 180-character line maps the split and re-merges - Shape:
AGENTS.md:28decision index: a title grew into a two-clause sentence
Junior A, decided by:
- Locality, Navigation:
src/markdown/portable/task-list.ts:5splitTaskList: one function decides for reader and writer, where each had its own rule - Locality:
src/markdown/parse/markdown-to-adf.ts:86readBlocks:bulletNodereturns an unfinished shape only the caller completes - Locality:
src/adf/inline-nodes.ts:3InlineNodeModel.takesMarks: the hard break's rule lives in one row both directions read - Shape:
src/markdown/portable/task-list.ts:5splitTaskList: a carriedstandingflag, a reassignedstands, andheldTask's name hides the conversion - Navigation:
src/markdown/parse/markdown-to-adf.ts:22imports: both converters lead to the same named file
2026-10-09T12:35:05Z, PR #24 at e487fa4, against 78655bc
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | same | same | better |
| Inherited architect | better | better | same | better | better |
Mid A, decided by:
- Locality, Overall:
src/markdown/portable/adf-to-portable-markdown.ts:289reduceTaskList: a plain collect loop handing the list tosplitTasks, where the base carried anestedaccumulator andnestInmutatedtasks - Locality:
src/markdown/portable/task-list.ts:6splitTaskList: reader and writer share one rule, wherebulletNodeandnestIneach encoded it - Locality, Shape:
src/markdown/parse/markdown-to-adf.ts:84readBlocks: the portable task list is caught beforereadBlock, which depends on that order - Shape:
src/markdown/portable/task-list.ts:33itemParts:paragraphsandnestedare indices named like collections, and the demotion totaskItemis unnamed - Navigation, Shape:
src/adf/block-nodes.ts:92isTaskItem: one findable predicate, against one more hop from a parse symptom
Inherited architect, decided by:
- Locality, Navigation, Overall:
src/markdown/portable/task-list.ts:6splitTaskList: one unit decides where a task item's blocks go, for reader and writer - Locality, Shape:
src/markdown/portable/adf-to-portable-markdown.ts:289reduceTaskList: one pass then one call, no state carried across iterations - Self-sufficiency, Locality:
src/adf/inline-nodes.ts:5takesMarks: the hard-break rule is a field both directions read - Shape:
src/markdown/portable/task-list.ts:33itemParts: an index overcontentused overrun, andnestedrunning into the siblings - Shape, Locality:
src/markdown/parse/markdown-to-adf.ts:84readBlocks: a third special case ahead of the dispatch - Shape:
src/adf/block-nodes.ts:92isTaskItem: one predicate replaces two copies - Self-sufficiency:
src/markdown/portable/task-list.ts:5comment: states the schema limit and what follows from it
2026-10-09T13:03:22Z, PR #25 at 2b211e9, against 875c0e5
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | same | better |
| Inherited architect | same | better | better | same | better |
Mid A, decided by:
- Locality, Shape, Overall:
src/markdown/portable/adf-to-portable-markdown.ts:118portableSequence: a plain splice withindex -= 1, where the base merged neighbours after every splice throughspliced,mergedLists,joinedListsandsplitTasks - Locality, Navigation:
src/markdown/parse/markdown-to-adf.ts:98listBreakFault: gone, with the base's look atblocks[index - 1]andblocks[index + 1]and the separator spelled in four places - Navigation, Shape:
src/markdown/parse/blocks.ts:232continuesList: one named predicate on kind and delimiter thatitemStartandopenedListshare - Locality:
src/markdown/emit/adf-to-markdown.ts:73joinBlocks: a toggledalternatedflag decides each list's text from the one before it, andisOrderedcounts a task list as a bullet list unsaid - Shape:
src/markdown/emit/adf-to-markdown.ts:334spelledList:tryListbuilds both spellings then falls back once, andtryTaskListshares the helper
Inherited architect, decided by:
- Locality, Shape, Overall:
src/markdown/portable/adf-to-portable-markdown.ts:118portableSequence: a filter and a loop ending inindex -= 1, where the base kept the splice window, the merge rules and the renumbering-as-text rule together - Locality, Shape:
src/markdown/parse/markdown-to-adf.ts:79readBlocks: reads one block at a time, where the base judged a separator by its siblings - Locality:
src/markdown/emit/adf-to-markdown.ts:73joinBlocks: a toggle carried across iterations sends a third adjacent list back to-, seen only by tracing - Shape:
src/markdown/emit/adf-to-markdown.ts:334spelledList: the both-or-neither rule is one uncommented expression - Self-sufficiency:
src/markdown/emit/adf-to-markdown.ts:369tryListItemLines:inner.startsWith('*')depends on the alternate bullet being*, and the comment needs the inline escaping worked out - Self-sufficiency:
src/markdown/parse/blocks.ts:232continuesList: states the rule the base sent the reader to the spec for
2026-10-09T13:37:16Z, PR #25 at ca3d703, against 875c0e5
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | better | better |
| Inherited architect | better | better | better | same | better |
Mid A, decided by:
- Locality, Shape, Overall:
src/markdown/portable/adf-to-portable-markdown.ts:118portableSequence: a worklist that keeps a block that spells or pushes its items back, where the base spliced, merged neighbours and stepped the index back by hand - Navigation, Locality:
src/markdown/parse/markdown-to-adf.ts:70readBlocks: handles each block alone, where the base judged a separator by its neighbours across five places - Shape, Self-sufficiency:
src/markdown/parse/blocks.ts:232continuesList: one named predicate on kind and delimiter, its rule stated in place - Self-sufficiency, Locality:
src/markdown/emit/adf-to-markdown.ts:27SpelledBlock: its comment states whyalternateTextexists, thoughjoinBlocksnow carries a toggle across siblings - Shape:
src/markdown/emit/adf-to-markdown.ts:334spelledList: line building in small units, the fallback once after the loop, shared bytryTaskList - Self-sufficiency:
src/markdown/emit/adf-to-markdown.ts:369tryListItemLines: the*branch's comment needs a reread
Inherited architect, decided by:
- Locality, Shape, Overall:
src/markdown/portable/adf-to-portable-markdown.ts:118portableSequence: a work stack replacing six helpers and the base's cursor rewind - Locality, Navigation:
src/markdown/parse/markdown-to-adf.ts:70readBlocks: each block reads alone, and two merged lists lead to one emitter and one parser unit - Locality, Navigation:
src/markdown/parse/blocks.ts:232continuesList: a list continues exactly where CommonMark says, checkable without the spec - Locality:
src/markdown/emit/adf-to-markdown.ts:72joinBlocks: a block's spelling depends on the run before it, where the base's separation was a pure function of a pair - Shape:
src/markdown/emit/adf-to-markdown.ts:334spelledList: one exit to the directive form, though bullets pass() => ''as the number - Self-sufficiency:
src/markdown/emit/adf-to-markdown.ts:369tryListItemLines: the*branch needs the spec open, cancelling the spec pointers removed
2026-10-09T14:50:52Z, PR #27 at 2378782, against a9fedb3
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | better | better |
| Inherited architect | better | better | better | same | better |
Mid A, decided by:
- Locality, Self-sufficiency:
src/markdown/inline-tokens.ts:20readInlineToken: the parser and the escaper ask one function what the reader takes at a character, where each held its own copy of the rules - Locality, Shape:
src/markdown/emit/line-escaping.ts:102escapeClaims: the order-dependentafterEscapeandpairsEqualsflags are gone; runs go whole toescapeRunand fixed inputs ride oneEscapeWalkrecord - Shape, Navigation:
src/markdown/parse/inline-content.ts:110scanInline: a two-level character dispatch and eight helpers became one switch over token kinds - Shape:
src/markdown/emit/line-escaping.ts:158claimsCharacter: switches ontoken.kindin place of a chain of character tests
Inherited architect, decided by:
- Navigation, Shape:
src/markdown/inline-tokens.ts:20readInlineToken: one tokenizer answers what the reader sees at an index, where two parallel implementations had to agree - Locality:
src/markdown/emit/line-escaping.ts:112escapeClaims: each step reads on its own, no flag carried from the previous character - Shape:
src/markdown/emit/line-escaping.ts:158claimsCharacter: switches on the token kind and takes the shared record; the heading closer is worked out once inclosingHashes - Shape, Navigation:
src/markdown/parse/inline-content.ts:121readToken: one exhaustive switch overInlineToken['kind']replaces a two-level dispatch - Locality:
src/markdown/emit/line-escaping.ts:173claimsCharacter:default: return trueclaims every kind it does not name, so a new kind is escaped without its author deciding
2026-10-09T17:14:17Z, PR #27 at 65d2a26, against a9fedb3
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | same | better |
| Inherited architect | better | better | better | same | better |
Mid A, decided by:
- Navigation, Locality:
src/markdown/inline-tokens.ts:21readInlineToken: the one place that says what a character opens, which the reader and the escaper both dispatch on, where each held a copy that could drift - Locality, Shape:
src/markdown/emit/line-escaping.ts:156claimsCharacter: a flat switch on the token kind over a readonlyEscapeWalk, where one character's escape hung on flags the previous iteration set - Shape:
src/markdown/parse/inline-content.ts:121readToken: one flat switch, recognition in the tokenizer and action here, where a two-level character switch fanned out to eight helpers - Locality:
src/markdown/directive-syntax.ts:14ClaimedPrefix: the directive read can no longer answer that no prefix stands there - Shape:
src/markdown/emit/line-escaping.ts:147claimsRunRest: re-reading each suffix of a run is a step the name does not say
Inherited architect, decided by:
- Navigation, Locality:
src/markdown/inline-tokens.ts:21readInlineToken: the 3am symptom of an unescaped character leads to one file both directions ask - Locality, Shape:
src/markdown/emit/line-escaping.ts:156claimsCharacter: an exhaustive switch read one case at a time, where the decision needed replaying the loop forpairsEquals - Shape, Locality:
src/markdown/parse/inline-content.ts:121readToken: one pure tokenizer and one switch that applies tokens - Shape:
src/markdown/directive-syntax.ts:14ClaimedPrefix: the directive read needs proof of its prefix, and the misnamedopensConstructis gone - Locality:
src/markdown/emit/line-escaping.ts:112escapeClaims: the escaper steps one character at a time while the reader steps by token, which only the==comment explains
2026-10-10T09:16:56Z, PR #30 at 6182ba6, against c11aa91
Ruling: worse
Fell: Locality. Under the floor of 7.0: Locality 5.63, so the same ruling counts as worse.
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | same | same | same |
| Inherited architect | better | worse | same | same | same |
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Junior A | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Mid A | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Maintainability senior | 7 | 6 | 6.5 | 6 | 6 |
| Inherited architect | 6.5 | 5.5 | 6 | 6 | 6 |
| Mean | 6.88 | 5.63 | 6.38 | 5.75 | 6.00 |
Mid A, decided by:
- Locality:
src/markdown/parse/blocks.ts:79Walk.endedByDefinitions: written incloseLeafat:469and read inopenedListat:257, never cleared, correct only by identity withblocks.at(-1);closeLeaftakes on recording where definitions ended a list
Inherited architect, decided by:
- Locality:
src/markdown/parse/blocks.ts:79Walk.endedByDefinitions: a never-reset fieldcloseLeafwrites andopenedListreads, right only by identity and byopenContainersclosing before it opens; reordering those steps breaks the split silently - Locality:
src/markdown/parse/blocks.ts:432readLineBlock: a second path that can find a paragraph emptied by definitions records nothing, which a reader must prove harmless by hand - Navigation:
src/markdown/parse/blocks.ts:252openedList: the comment names the exception, so a reader of two lists merged or not lands on the right unit - Navigation:
README.md:242the CommonMark exceptions bullet: each exception is named rather than counted by position - Navigation:
CHANGELOG.md:5## Unreleased: breaking entries come first, other changes last
2026-10-11T10:33:32Z, PR #32 at be23835, against c11aa91
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | same | worse | worse |
| Inherited architect | same | worse | worse | worse | worse |
Mid A, decided by:
- Overall, Locality, Self-sufficiency:
src/markdown/parse/markdown-to-adf.ts:229splitPath: builds stand-in nodes and replayssplitTaskListto place a refused block's path, checkable only by knowing how the split moves blocks - Locality, Self-sufficiency:
src/markdown/portable/task-list.ts:23splitPlace: finds the stand-in by object identity, which holds only whiletaskOfParagraphskeeps the original children, and nothing there says so - Locality:
src/markdown/parse/blocks.ts:262endList:closeLeaffillsWalk.endedListsandopenedListreads it, whereopenedListlooked only at the previous block
Inherited architect, decided by:
- Locality, Self-sufficiency, Overall:
src/markdown/parse/markdown-to-adf.ts:229splitPath: a fake task list replayed throughsplitTaskListand found again by identity; iftaskOfParagraphsever copies nodes the old wrong path returns silently - Shape, Locality:
src/markdown/parse/markdown-to-adf.ts:203bulletBlocks: onereadBlockscall became a per-block loop with a hand-built failure, a second depth check and a fan-out throughtaskItems,splitPath,childTypeandsplitPlace;Refusalnames a context bag - Locality:
src/markdown/parse/blocks.ts:78Walk.endedLists: identity-keyed walk state thatcloseLeafwrites andopenedListreads - Shape:
src/markdown/portable/adf-to-portable-markdown.ts:354reduceMedia: the callback'sheldshadows the alt's, and the link goes mark to definition to mark
2026-10-11T10:33:35Z, PR #32 at be23835
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Junior A | 7 | 6 | 6.5 | 6 | 6.5 |
| Mid A | 7 | 6 | 6.5 | 5.5 | 6 |
| Maintainability senior | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Inherited architect | 6.5 | 5.5 | 6 | 6 | 6 |
| Mean | 6.88 | 5.75 | 6.38 | 5.75 | 6.13 |
Junior A, hardest first:
- Locality:
src/markdown/parse/markdown-to-adf.ts:229splitPath: replayssplitTaskList's internals to name a path - Self-sufficiency:
src/markdown/emit/line-escaping.ts:189escapeClosedRuns: the escaping rule lives inspec/flavour.md
Mid A, hardest first:
- Locality:
src/markdown/emit/adf-to-markdown.ts:30SpellingMemo: reference-keyed memo shared by parse and emit - Self-sufficiency:
src/markdown/parse/inline-content.ts:62Scan: rules read withspec/flavour.mdopen alongside
Maintainability senior, hardest first:
- Locality:
src/markdown/parse/markdown-to-adf.ts:257directiveNode: the parser asks the emitter whether input was legal - Self-sufficiency:
src/markdown/emit/line-escaping.ts:189escapeClosedRuns: needsspec/flavour.mdEscaping open
Inherited architect, would restructure first:
- Navigation:
src/markdown/portable/conventions.ts:23flavourClaims: every flavour's switchboard sits inportable/ - Locality:
src/markdown/emit/adf-to-markdown.ts:117readableBlock: reader acceptance hangs on emitter verdicts
2026-10-11T11:29:00Z, PR #32 at 27c8f9b, against c11aa91
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | same | same | worse |
| Inherited architect | same | worse | same | same | worse |
Mid A, decided by:
- Locality, Overall:
src/markdown/parse/markdown-to-adf.ts:229splitPath: rewrites a refused path by replayingsplitTaskListon stand-in nodes, so a change to the split moves error paths quietly - Locality:
src/markdown/parse/blocks.ts:262endList:closeLeafwritesWalk.endedListsandopenedListreads it later
Inherited architect, decided by:
- Locality, Overall:
src/markdown/parse/markdown-to-adf.ts:229splitPath: four facts held at once, the mutatedtask.content, the path slice, the stand-ins and a second parse inchildType - Locality:
src/markdown/portable/task-list.ts:23splitPlace: finds the refused node by object identity, right only whiletaskOfParagraphskeeps its children
2026-10-11T11:29:02Z, PR #32 at 27c8f9b
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Junior A | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Mid A | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Maintainability senior | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Inherited architect | 6.5 | 6 | 6 | 6.5 | 6.5 |
| Mean | 6.88 | 5.63 | 6.38 | 5.75 | 6.13 |
Junior A, hardest first:
- Locality:
src/markdown/parse/inline-content.ts:62Scan: a mutable bag many functions change - Self-sufficiency:
src/markdown/emit/line-escaping.ts:189escapeClosedRuns: the rule lives inspec/flavour.md
Mid A, hardest first:
- Locality:
src/markdown/parse/markdown-to-adf.ts:257directiveNode: the parser asks the emitter for verdicts - Self-sufficiency:
src/markdown/emit/line-escaping.ts:100escapeClaims: needs the spec open alongside
Maintainability senior, hardest first:
- Locality:
src/markdown/parse/inline-content.ts:62Scan: flags that act at a distance between escaper, emitter and parser - Self-sufficiency:
src/markdown/emit/line-escaping.ts:189escapeClosedRuns: no local statement of the escaping contract
Inherited architect, would restructure first:
- Navigation:
src/markdown/portable/conventions.ts:23flavourClaims: the table for all three flavours sits inportable/ - Shape:
src/markdown/emit/adf-to-markdown.ts:131spellReadableBlock: the flavour concern spread over three directories
2026-10-11T18:44:18Z, PR #35 at 0227c0b, against 4f00e60
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | same | same | same | better |
| Inherited architect | same | worse | worse | same | same |
| Maintainability senior | better | worse | same | same | same |
| Junior A | better | same | same | same | better |
Mid A, decided by:
- Navigation, Overall:
README.md:211"The calls": each public call sits in one row with the codes it refuses, where the base split that knowledge across prose bullets and the feature list - Navigation:
README.md:384"The errors": parsing, emitting and either direction have their own sub-headings, and the error shape is a bulleted list - Navigation:
src/result.ts:49withinEngineLimits: the refusal for output too long is visible at both public entry points, its message in one place
Inherited architect, decided by:
- Locality, Shape:
src/result.ts:49withinEngineLimits: one try/catch wraps each writer's whole call and matches four exact engine messages; a concatenation deep in the emitter does not show it is caught at the top, a reworded engine message turns the refusal back into a throw, andengineLimitFaultsborrows "fault" fromConvertFaultwhile holding plain strings - Shape:
src/result.ts:54withinEngineLimits: an engine overflow is reported asunsupported-node-shapeat an empty path, though the node shapes are fine and the output is what is too big - Locality:
src/canonical-json.ts:30writeCanonicalJson: one walker serves two callers through a stop-returningwritecallback, one more contract to hold when editingschedule
Maintainability senior, decided by:
- Locality:
src/result.ts:49withinEngineLimits: the guard sits only at the two public writers whilewriteMarkdownstays exported and unguarded and the readers rely on another mechanism; nothing states which paths can outgrow the engine's longest string - Locality:
src/result.ts:46engineLimitFaults: errors match exact engine strings, and why a stack overflow stays a throw is not said - Navigation:
README.md:211"The calls": one table maps each call to its refusal codes, where the base spread them over prose that was wrong foradfToPortableMarkdown - Navigation:
src/markdown/opaque-carry.ts:78readCarriedJson:spellsCanonicalJsonreads as plainly at the call site, with its reason beside it
Junior A, decided by:
- Navigation, Overall:
README.md:193"The calls": a table pairs each call with what it reads or writes and what it refuses, and a node-to-spelling table turns a symptom into a concept to grep for
2026-10-11T19:02:20Z, PR #35 at 90de6cb, against 4f00e60
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | same | same | same | better |
| Inherited architect | better | same | worse | better | better |
Mid A, decided by:
- Navigation, Overall:
README.md:211"The calls": each call's row says what it reads or writes and what it refuses, and the errors split by direction, where the base spread the codes across a prose list and paragraphs - Navigation:
src/result.ts:49withinEngineLimits: the engine-limit refusal lives in one wrapper, called once at each public writer
Inherited architect, decided by:
- Navigation, Self-sufficiency:
README.md:211"The calls": one row per call gives what it reads or writes and its refusal codes, where the base split them and left outunsupported-node-shapefor the portable writer - Self-sufficiency:
README.md:241"The lossless flavour": two tables map ADF types to their spellings, so the 3am case reads without the spec open - Shape:
src/result.ts:55withinEngineLimits: a length failure is reported underunsupported-node-shapeat an empty path, and the README cell explaining it holds four cases - Shape:
src/result.ts:45engineLimitThrows: matching exact engine message text rots silently when an engine rewords, and JavaScriptCore'sOut of memoryblurs a heap shortage with length
2026-10-12T15:56:53Z, PR #36 at 584b214, against 7a27f6b
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | worse | worse | same | worse |
| Inherited architect | better | worse | worse | same | worse |
Mid A, decided by:
- Locality, Shape, Overall:
src/markdown/emit/adf-to-markdown.ts:61walkBlocks: a running forecast depends onWriting.indent, which each container must pass correctly,tryListdeliberately not indenting - Shape, Locality:
src/markdown/emit/adf-to-markdown.ts:398spelledList: template strings becamejoinedWithinpiped through nestedboundedThencallbacks, andjoinedItemsrepeats the counting loop - Locality:
src/markdown/emit/adf-to-markdown.ts:147readableBlock: the memo is filled incommonMarkSpellingand emptied on read, so when an entry is present depends on call order across two functions - Shape:
src/markdown/directive-syntax.ts:114spellAttributes: each spelling exists twice, as a string and as a generator of pieces - Locality:
src/markdown/portable/editor-normal.ts:26toEditorNormal: editor normalization imports the markdown length bound - Locality:
src/markdown/portable/adf-to-portable-markdown.ts:126portableSequence: each block carries its source path, rebuilt by hand for a replacement - Navigation:
src/markdown/length-bound.ts:1withinEngineLimits: the bound, its refusal and the catch share one module named for them
Inherited architect, decided by:
- Locality, Shape:
src/markdown/emit/adf-to-markdown.ts:61walkBlocks: the forecast is a second length bound besidejoinedWithin, whose never-overcount rule fixes how every container walks - Locality:
src/markdown/emit/adf-to-markdown.ts:377tryList: whether items walk indented depends on whatspelledOrDirectiveListmay decide later - Locality:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: the emitter'sindentleaks into the parser and the portable reduction - Locality:
src/markdown/emit/adf-to-markdown.ts:147readableBlock: filling and emptying the memo split across two functions - Shape:
src/markdown/emit/adf-to-markdown.ts:194quotedBlock: nestedboundedThenreads as continuation passing where a template stood - Shape, Locality:
src/markdown/emit/pipe-table.ts:9tryPipeTable: the sum-then-check rule appears in seven shapes, and a reader cannot tell which is the real bound - Navigation, Shape:
src/markdown/length-bound.ts:41withinEngineLimits: a too-long symptom leads straight to the module named for it - Shape:
src/markdown/directive-syntax.ts:133spellDirectiveOpener: each spelling is a string function and a pieces generator - Shape:
src/markdown/opaque-carry.ts:64carriedJson: the lambda parameterspelledshadows the function's own
2026-10-12T16:40:52Z, PR #36 at acd22aa, against 7a27f6b
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | worse | worse | same | worse |
| Inherited architect | better | worse | worse | same | worse |
Mid A, decided by:
- Locality, Shape:
src/markdown/emit/adf-to-markdown.ts:374spelledList: a builder'sundefinednow means either no list spelling or past the length bound, and every caller ofjoinBlocksmust remember which it holds - Shape:
src/markdown/emit/adf-to-markdown.ts:383listLines: split, map and join became generators yielding pieces intoseparatedByandjoinedWithin, so a reader rebuilds the string in their head - Locality:
src/markdown/emit/adf-to-markdown.ts:125readableBlock: the memo is filled incommonMarkSpellingand deleted on read, a one-shot cache whose hits depend on which walk came first - Navigation:
src/markdown/length-bound.ts:41withinEngineLimits: a too-long refusal leads to a module named for it
Inherited architect, decided by:
- Locality, Shape:
src/markdown/emit/adf-to-markdown.ts:374spelledList:undefinedmeans two things a few lines apart, told apart only by the side of a nestedboundedThencallback - Locality:
src/markdown/emit/adf-to-markdown.ts:125readableBlock: reading the memo is a mutation, and a second read spells again - Shape:
src/markdown/pipe-table-syntax.ts:43pipeRowPieces: one-line templates became generators whose output cannot be read off one line - Locality, Shape:
src/markdown/emit/block-directive-spelling.ts:27spellBlockDirectiveOpener: the opener's layout is known here and inspellDirectiveOpener - Shape:
src/markdown/portable/adf-to-portable-markdown.ts:231reduceCodeBlock: an ADF-to-ADF reducer carries a markdown length bound through a callback - Navigation:
src/markdown/length-bound.ts:41withinEngineLimits: a too-long refusal leads straight to one small, well-named module
2026-10-12T19:45:45Z, PR #36 at 1f4551a, against 7a27f6b
Ruling: worse
Fell: Locality. Under the floor of 7.0: Locality 5.13, so the same ruling counts as worse.
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | worse | better | same | same |
| Inherited architect | better | worse | better | same | same |
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Junior A | 6.5 | 5 | 6 | 5.5 | 5.5 |
| Mid A | 7 | 5 | 6 | 5 | 5.5 |
| Maintainability senior | 7 | 5.5 | 6.5 | 6 | 6 |
| Inherited architect | 6.5 | 5 | 5.5 | 6.5 | 5.5 |
| Mean | 6.75 | 5.13 | 6.00 | 5.75 | 5.63 |
Mid A, decided by:
- Locality:
src/markdown/emit/adf-to-markdown.ts:114commonMarkSpelling: the memo is filled here and read-and-deleted inreadableBlock, a write-once, read-once protocol whose order is set in another module - Locality:
src/markdown/emit/adf-to-markdown.ts:52writeMarkdown: one rule, output pastlongestMarkdownis refused, is checked in six places with different triggers - Navigation, Shape:
src/markdown/length-bound.ts:1tooLong: a too-long refusal leads to one small module holding the bound, its message and the engine guard - Shape:
src/canonical-json.ts:23canonicalJsonPieces: a generator replaces a boolean-returning callback, and both readers become plain loops - Shape, Locality:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: a refused spelling is returned where it is produced, and each block carries its own path - Shape:
src/markdown/emit/inline-line.ts:235emitLeaf: one content-or-text check, and the path is built only to refuse
Inherited architect, decided by:
- Locality:
src/markdown/emit/adf-to-markdown.ts:114commonMarkSpelling: filling and consuming the memo split across an exported predicate and a private reader, a consume-once protocol among three callers - Locality:
src/markdown/emit/adf-to-markdown.ts:52writeMarkdown: one bound enforced at five sites in four files, and a new builder has nothing nearby saying whether it needs a check - Navigation, Shape:
src/markdown/length-bound.ts:1withinEngineLimits: an output-too-long symptom leads straight to a module named for it - Navigation:
src/markdown/parse/markdown-to-adf.ts:47readDocument: the parse takes the same guard as both writers - Shape:
src/canonical-json.ts:23canonicalJsonPieces: plain loops replace a boolean-returning callback - Shape:
src/markdown/emit/inline-line.ts:235emitLeaf: both leaf emitters return a plain emission, the path built only on refusal
Junior A, hardest first:
- Locality:
src/markdown/emit/adf-to-markdown.ts:114commonMarkSpelling: a mutable memo shared by three walks, deleted on read and rebased by depth
Mid A, hardest first:
- Locality:
src/markdown/emit/adf-to-markdown.ts:125readableBlock: shared mutable state with no single owner, parse and emit coupled both ways
Maintainability senior, hardest first:
- Locality:
src/markdown/emit/adf-to-markdown.ts:114commonMarkSpelling: the parser and the portable reducer call into the emitter and share a reference-keyed, delete-on-read memo
Inherited architect, would restructure first:
- Locality:
src/markdown/emit/adf-to-markdown.ts:126readableBlock: the memo is mutated and deleted across parse, emit and portable, and the length bound is applied at five sites
2026-10-13T14:48:38Z, PR #37 at ecd695a, against 7a27f6b
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | worse | better | worse | worse |
| Inherited architect | better | worse | same | worse | worse |
Mid A, decided by:
- Locality, Self-sufficiency:
src/markdown/emit/adf-to-markdown.ts:116commonMarkSpelling/readableBlock/takeKeptSpelling: only commonMarkSpelling fills the memo and a read empties it, so whether an entry exists depends on which caller ran first; the reason lives only behind a pointer to docs/decisions.md - Locality:
src/markdown/emit/line-escaping.ts:229escapeClosedRuns: both steps write one shared Uint8Array, and correctness rests on the scan order a second comment line must defend - Navigation, Shape:
src/markdown/length-bound.ts:30withinEngineLimits: the engine-limit catch moves out of result.ts into one well-named file, with string-length and engine limits apart andengine-limita code of its own - Locality:
src/markdown/emit/adf-to-markdown.ts:51writeMarkdown/walkBlocks/commonMarkSpelling: the length bound is enforced in layers a reader changing it must hold together - Shape:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: undefined is wrapped into a Result to pass the engine guard, then unpicked - Shape:
src/markdown/emit/line-escaping.ts:35Escapings: the type is a lookup function, its comment describes the Uint8Array behind it;backslashedadds 4096-piece chunking - Shape, Locality:
src/canonical-json.ts:23canonicalJsonPieces: a generator replaces a boolean-continue callback - Shape:
src/markdown/emit/inline-line.ts:235emitLeaf: the content-or-text refusal moves into one place - Locality:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: a spelling refusal propagates where it was swallowed, at the cost of Sourced path plumbing
Inherited architect, decided by:
- Locality, Self-sufficiency:
src/markdown/emit/adf-to-markdown.ts:139takeKeptSpelling: reading deletes the entry and only commonMarkSpelling fills it, so readableBlock is right only if another file's caller asked first, once per node; explained only by a pointer to docs/decisions.md - Locality, Shape:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: a second withinEngineLimits inside readDocument's, fed?? success(undefined), so null and undefined carry meaning the reader must remember - Locality:
src/markdown/emit/adf-to-markdown.ts:58walkBlocks: the length bound is enforced at about six sites across three files - Navigation:
src/markdown/length-bound.ts:30withinEngineLimits: engine-limit handling sits in a file named for it, and the engine-limit code parts memory from the length bound - Shape, Locality:
src/markdown/emit/line-escaping.ts:229escapeClosedRuns: mutates its input in place and needs a two-line comment arguing it is safe; output joined in batches of 4096 - Locality, Shape:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: a refusal propagates with its source path, where it was swallowed - Shape:
src/markdown/emit/inline-line.ts:235emitLeaf: one place refuses content and text, and a generator replaces the boolean-callback JSON writer
2026-10-13T15:35:32Z, PR #37 at 025ccc0, against 7a27f6b
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | worse | same | same | worse |
| Inherited architect | better | worse | same | worse | worse |
Mid A, decided by:
- Locality:
src/markdown/emit/adf-to-markdown.ts:58walkBlocks: the length bound is enforced at six sites across four files, each comment giving only its own reason, where one wrapper covered the conversion - Locality:
src/markdown/emit/adf-to-markdown.ts:126readableBlock: the memo is emptied on read and filled only whenasked, so whether a spelling is cached depends on call order and caller - Navigation:
src/markdown/length-bound.ts:1withinEngineLimits: a refused long document leads to a file named for the problem, holding the bound, both throw lists and both messages - Locality:
src/markdown/parse/markdown-to-adf.ts:266directiveNode:success(undefined)andsuccess(null)encode the ask's answer, decoded only by tracing commonMarkSpelling - Shape:
src/canonical-json.ts:23canonicalJsonPieces: a generator replaces a boolean-continue callback - Shape:
src/markdown/emit/line-escaping.ts:38PlacedSegment: segment placements drop the cursor arithmetic two functions repeated - Shape:
src/markdown/emit/line-escaping.ts:113backslashed: byte flags, codes and 4096-piece joins read harder than a character loop - Locality:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: a refused spelling propagates where it was silently swallowed
Inherited architect, decided by:
- Locality:
src/markdown/emit/adf-to-markdown.ts:58walkBlocks: one rule, no markdown past longestMarkdown, is checked at about seven places across four files - Locality, Shape:
src/markdown/emit/adf-to-markdown.ts:126readableBlock: a read deletes the entry and a bare positionalaskedboolean decides what is stored, so results depend on call order - Locality, Self-sufficiency:
src/markdown/emit/line-escaping.ts:113backslashed: flags, byte codes, a lookup closure and batched joins take more passes to read as putting a backslash before characters - Self-sufficiency:
src/markdown/emit/adf-to-markdown.ts:65walkBlocks: the refusal's comment makes sense only once you know V8's limit applies on every engine, which lives in docs/decisions.md; tooLong carries path [] though the walk knows the path - Shape:
src/markdown/length-bound.ts:17tooLong: the length refusal keeps unsupported-node-shape while engine-limit got a name of its own; directiveNode folds three outcomes into one Result to fit the wrapper - Navigation:
src/markdown/length-bound.ts:37withinEngineLimits: the engine guard moves out of the Result module, and engine-limit leads from the symptom to it - Shape, Locality:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: a refusal propagates with its block's path, where it was silently swallowed - Shape:
src/canonical-json.ts:23canonicalJsonPieces: a generator, emitLeaf's one refusal and PlacedSegment each read simpler than before
2026-10-13T15:41:57Z, PR #37 at f1ea9fd, against 7a27f6b
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | worse | better | same | same |
| Inherited architect | better | worse | same | same | worse |
| Maintainability senior | better | worse | better | same | same |
| Junior A | better | worse | better | same | same |
Mid A, decided by:
- Locality:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: a second engine guard inside the parse's own, explained by how each engine overflows - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: a caller flag decides the fill and every read deletes, so what a later call sees depends on who called first - Locality:
src/markdown/emit/adf-to-markdown.ts:66walkBlocks: the length bound is checked at four points, each relying on the others to cover what it skips - Navigation, Shape:
src/markdown/length-bound.ts:37withinEngineLimits: engine and length refusals have their own file and code, and result.ts is back to types - Shape:
src/markdown/length-bound.ts:17tooLong: a string overflow keeps unsupported-node-shape while array and memory take engine-limit, explained only by a comment - Shape, Locality:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: a failed spelling returns early with each block's own path, where it was swallowed - Shape:
src/markdown/emit/adf-to-markdown.ts:117commonMarkSpelling: returns Result, which says what it means, where undefined and success(null) encoded the answer - Shape:
src/canonical-json.ts:23canonicalJsonPieces: a generator replaces a boolean early-stop callback - Shape:
src/markdown/emit/line-escaping.ts:113backslashed: PlacedSegment drops repeated cursor arithmetic, at the cost of byte codes, chunked joins and RunEscapes
Inherited architect, decided by:
- Locality:
src/markdown/emit/adf-to-markdown.ts:126readableBlock: a read deletes and only an asked caller fills, so whether a node is spelled again depends on call order; the first place to rot - Locality, Navigation:
src/markdown/length-bound.ts:36withinEngineLimits: wrap-every-builder is a project-wide duty, and six sites refuse with one message and path [], so a report cannot say which fired - Navigation:
src/markdown/length-bound.ts:1withinEngineLimits: the size concern has a file named for it and engine refusals their own code - Locality:
src/markdown/parse/markdown-to-adf.ts:265directiveNode: a nested engine guard mid-walk, there only to place V8's throw at this directive - Shape:
src/markdown/emit/adf-to-markdown.ts:117commonMarkSpelling: Result tells the truth and a refusal now propagates with its path; line 134's conditional is dense - Shape:
src/markdown/emit/line-escaping.ts:40RunEscapes: byte flags, codes and batched joins read less directly, andescapablereads close to backwards; PlacedSegment is a real gain
Maintainability senior, decided by:
- Navigation, Shape:
src/markdown/length-bound.ts:37withinEngineLimits: guard, bound and refusals share one file, and result.ts is back to describing results - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: deletes on every read and writes only when asked, so a hit depends on call order across the parser, the portable reduction and the walk - Locality, Self-sufficiency:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: a check's place is justified by where V8 would throw, with a nested engine guard, so moving one needs V8's behaviour reconstructed - Locality:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: a refused spelling comes back as a value with its block's path, where it was swallowed - Shape:
src/markdown/emit/adf-to-markdown.ts:117commonMarkSpelling: Result where absence coded both answers - Shape:
src/markdown/length-bound.ts:17tooLong: a length refusal under unsupported-node-shape with path [], and the README row grown into a catch-all - Shape:
src/markdown/emit/line-escaping.ts:113backslashed: byte codes and chunked joins against PlacedSegment removing duplicated cursor arithmetic, about even - Shape:
src/canonical-json.ts:23canonicalJsonPieces: a generator replaces a boolean-returning callback - Locality:
src/markdown/emit/inline-line.ts:235emitLeaf: the content-or-text refusal is hoisted once, a small gain
Junior A, decided by:
- Navigation, Shape:
src/markdown/length-bound.ts:37withinEngineLimits: the engine-overflow catch moves out of result.ts into a file named for the job, with the two message lists saying which throw means what - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: a read deletes and a caller flag decides the store, an order dependence across three files - Locality:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: a nested engine guard to pin V8's throw, and the bound checked in five places - Shape, Locality:
src/markdown/emit/adf-to-markdown.ts:117commonMarkSpelling: Result matches its name, and portableSequence propagates a refusal with each block's path - Shape:
src/markdown/emit/line-escaping.ts:38PlacedSegment: replaces a parallel placements array and hand-advanced cursor, against byte codes and chunked joins - Shape:
src/canonical-json.ts:23canonicalJsonPieces: a generator replaces a write callback threading a keep-going flag - Shape:
src/markdown/emit/inline-line.ts:175heldContentOrText: the content-or-text refusal checked once in emitLeaf
2026-10-13T18:05:39Z, PR #37 at 3ba3a82, against 7caa823
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | same | better |
| Inherited architect | better | better | better | better | better |
Mid A, decided by:
- Shape:
src/markdown/emit/adf-to-markdown.ts:117commonMarkSpelling: returns Result, where undefined and success(null) had to be decoded from the callers - Shape, Locality:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: one boolean test where a typed guard, a fallback and an undefined check decoded the tri-state again - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: every memo read, delete and write sits in one function, where three held its life cycle - Navigation:
src/markdown/length-bound.ts:52engineLimit: an engine-limit refusal has its own code and constructor, where it shared unsupported-node-shape with shape refusals - Shape, Locality:
src/markdown/portable/adf-to-portable-markdown.ts:128portableSequence: one check on spelled.value, and a flatMap replaces listItemBlocks - Locality:
src/markdown/emit/line-escaping.ts:38PlacedSegment: computed once and passed on, where three functions each re-derived starts with their own cursor - Shape:
src/markdown/emit/line-escaping.ts:52escapingCodes: byte codes, flags and a 4096-piece join, and the RunEscapes union, read harder than a plain list
Inherited architect, decided by:
- Navigation, Self-sufficiency:
src/result.ts:2ConvertErrorCode: engine-limit names its cause and points at one function, where the most overloaded code hid whether the document or the runtime failed - Shape, Locality:
src/markdown/emit/adf-to-markdown.ts:117commonMarkSpelling: Result, so directiveNode tests one boolean where it decoded a tri-state - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: the memo's read, delete and write sit in one function under one comment, at the cost of a caller flag - Shape, Self-sufficiency:
src/markdown/portable/adf-to-portable-markdown.ts:134portableSequence: one boolean test, though the list's own path for its items is now stated only in the README - Locality:
src/markdown/emit/line-escaping.ts:38PlacedSegment: each segment arrives with its start, so two functions no longer walk in step; backslashed itself reads costlier - Shape:
src/markdown/emit/line-escaping.ts:41RunEscapes: its field collides with isEscapable and the call site handles false first, the slowest spot to read - Self-sufficiency:
src/markdown/length-bound.ts:43withinEngineLimits: the stack-overflow comment sits on its line, the carry comment says why the join is bounded
2026-10-13T22:23:11Z, PR #40 at 8d14bbf, against 341280d
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | better | same | same |
| Inherited architect | same | better | better | same | better |
| Maintainability senior | worse | same | better | same | same |
| Junior A | same | same | better | better | better |
Mid A, decided by:
- Shape:
src/markdown/directive-syntax.ts:109slotFault: both branches return unsupported-node-shape through its constructor, where one small function returned two codes and the old name sounded like a writer's failure
Inherited architect, decided by:
- Shape, Locality:
src/markdown/directive-syntax.ts:109slotFault: one rule with one code, where two branches gave the same kind of problem different codes and the reason lay outside the function - Shape:
src/result.ts:1ConvertErrorCode: the list loses a code named for writing that only the parser raised, so every name matches its producer
Maintainability senior, decided by:
- Shape:
src/markdown/directive-syntax.ts:109slotFault: the two checks raise one code, where sibling refusals of one slot took different codes under a name untrue twice over - Navigation:
README.md:451unsupported-node-shape: a symptom arrives as a code many sites raise, and its longest cell grows, so a reader searches on the message text where one row and one producer led straight there
Junior A, decided by:
- Shape:
src/result.ts:1ConvertErrorCode: the list loses a writer-named code only the parser raised - Shape, Self-sufficiency:
src/markdown/directive-syntax.ts:109slotFault: one code for both branches, and the message states the rule and the fix that lived only in the README
2026-10-13T23:14:24Z, PR #41 at d1dc155, against e0ead52
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | better | same |
| Inherited architect | same | worse | worse | better | worse |
| Maintainability senior | same | same | worse | same | same |
| Junior A | same | same | same | better | same |
Mid A, decided by:
- Self-sufficiency:
src/markdown/directive-syntax.ts:108slotFault: the comment now names the node the emitter carries, where "such" pointed at nothing in view - Self-sufficiency:
src/markdown/portable/conventions.ts:13Claims.pipeTables: the three-valued claim's comment says what each value accepts, so every check in blocks.ts reads without the spec
Inherited architect, decided by:
- Locality, Overall:
src/markdown/parse/blocks.ts:381readBlockLine/openLeaf/openGfmTable/pipeTableRow/pipeTableBlock/bareTableFault: a three-valued claim tested in six places with four comparisons, and no single place states what each mode does to a table - Locality:
src/markdown/parse/blocks.ts:497openGfmTable: cuts the open paragraph through walk.leaf, closes it, then sets walk.leaf again, an order on shared state; its call must precede the pipeCells branch and nothing says so - Shape:
src/markdown/portable/conventions.ts:14Claims.pipeTables:'flavour'names the lossless rule though every reader is a flavour, so=== 'flavour'needs the field's comment to decode - Shape:
src/markdown/parse/blocks.ts:514pipeTableRow: oneifmerges three reasons into "return cells", two of which mean "end the table"; the indentation guard is duplicated at two call sites - Self-sufficiency:
src/markdown/parse/blocks.ts:496openGfmTable,pipeTableRow: each opens with a "GFM, Tables:" line stating the rule it enforces
Maintainability senior, decided by:
- Shape:
src/markdown/portable/conventions.ts:14Claims.pipeTables:'flavour'names only the lossless reader's strict rule though portable is a flavour too, and blocks.ts tests the three states three ways - Locality:
src/markdown/parse/blocks.ts:497openGfmTable: rewrites walk.leaf, closes it, then installs the table, and its call must precede the pipeCells claim and the setext check with no comment saying so - Locality:
src/markdown/parse/blocks.ts:63ParagraphLine: each line keeps its position, where two parallel arrays had to stay the same length
Junior A, decided by:
- Self-sufficiency:
src/markdown/directive-syntax.ts:108slotFault: the comment says on its own which node the emitter carries - Self-sufficiency:
src/markdown/portable/conventions.ts:13Claims.pipeTables: the comment says what each mode reads, so the branches in blocks.ts read without the spec
2026-10-14T08:45:14Z, PR #43 at b83adc4, against e193536
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | worse | same | worse |
| Inherited architect | same | worse | worse | same | worse |
Mid A, decided by:
- Locality:
src/markdown/parse/directive-nodes.ts:140readNamedMark: words its error by deleting; ${directiveEscape}from a fault built in directive-syntax.ts, so rewording that message silently changes this one - Shape, Locality:
src/markdown/parse/directive-nodes.ts:100readMarks/readMarkArray/readNamedMarks/readNamedMark: one attribute's parse now spans four units and three modules, a cursor-driven list parser in a file about directive nodes - Shape:
src/markdown/directive-syntax.ts:299readAttributes/readDirectiveName: exported but left among the private helpers, below the file's export block - Locality:
src/markdown/directive-syntax.ts:69attributeValue: the numbers branch reads a JSON array only for a respelling check that lives in another file
Inherited architect, decided by:
- Locality, Overall:
src/markdown/parse/directive-nodes.ts:140readNamedMark: strips the escape hint with a string replace tied to the wording of pairFault and prefixFault in directive-syntax.ts, which nothing there warns of - Locality, Shape:
src/markdown/parse/directive-nodes.ts:117readNamedMarks/readNamedMark: a grammar inside a quoted attribute value, two levels of escaping held at once, the reader in a file otherwise about building nodes and the writer in block-directive.ts - Shape:
src/adf/mark-attributes.ts:22markVocabularies/markAttributes/isMarkType: markAttributes silently means inline marks beside markVocabularies meaning all, and isMarkType('alignment') is false
2026-10-14T08:45:16Z, PR #43 at b83adc4
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Junior A | 6.5 | 5 | 6 | 5 | 5.5 |
| Mid A | 6 | 5 | 5.5 | 5 | 5.5 |
| Maintainability senior | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Inherited architect | 7 | 6 | 6 | 6.5 | 6.5 |
| Mean | 6.63 | 5.38 | 6.00 | 5.50 | 5.88 |
Junior A, hardest first:
- Locality, Overall:
src/markdown/parse/markdown-to-adf.ts:237splitPath: builds stand-in nodes and re-runs splitTaskList to find an error path, the comments naming the trick but not why it is correct - Locality, Self-sufficiency:
src/markdown/emit/line-escaping.ts:230escapeClosedRuns/escapeClaims: per-character flags in Uint8Arrays and a backward-filled set of backtick lengths, opaque without the spec open - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: an identity-keyed memo deleted on read and filled by the parser and the portable writer, action at a distance - Locality:
src/markdown/parse/inline-content.ts:330closeBracket: mutable Scan flags set mid-scan and read later, then a call back into the emitter to decide a parse error - Shape:
src/markdown/emit/inline-line.ts:82emitLine: a retry loop widening a carried index set threaded through nested emitRun calls - Shape:
src/markdown/portable/inline-reduction.ts:194trimmedEdges: two nested fixpoint loops and a number-or-undefined edge depth
Mid A, hardest first:
- Locality, Self-sufficiency:
src/markdown/emit/line-escaping.ts:142escapeClaims/escapeClosedRuns: three passes over a Uint8Array whose conditions tie escaping kind, token kind and position, unverifiable against the spec's prose - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: filled only on an asked call, deleted on any read, so correctness depends on the order two directions call it - Locality:
src/markdown/parse/markdown-to-adf.ts:237splitPath: stand-in nodes and a re-run split to report an error path - Locality:
src/markdown/emit/inline-line.ts:82emitLine: a fixpoint loop the parser re-enters through openingLinkTakesDirective - Shape:
src/markdown/portable/conventions.ts:24flavourClaims: the switch every reader and writer uses lives under portable/ - Shape:
src/markdown/directive-syntax.ts:32Read: the general reader-failure type defined in the directive grammar file
Maintainability senior, hardest first:
- Locality, Overall:
src/markdown/parse/markdown-to-adf.ts:237splitPath: rebuilds a fake task list to place a refusal, correct only by knowing how splitTaskList and splitPlace move children - Self-sufficiency:
src/markdown/emit/line-escaping.ts:142escapeClaims/escapeClosedRuns: four escaping kinds and three special cases at once, complete only against spec §Canonical form - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: a reference-keyed memo with delete-on-read and depth rebasing, called from the parser and the portable reducer - Shape:
src/markdown/parse/inline-content.ts:443resolveNodes/pairedHighlights: parallel pieces and nodes arrays, a cursor advanced inside an index expression, and a seven-way Piece union - Shape:
src/markdown/portable/conventions.ts:8Claims: sets all three readers' behaviour yet lives under portable/
Inherited architect, would restructure first:
- Shape, Navigation:
src/markdown/portable/conventions.ts:8Claims/flavourClaims: the switch for all three flavours filed under the portable directory - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: the parse-to-emit dependency runs through a reference-keyed SpellingMemo shared across calls - Shape:
src/markdown/parse/markdown-to-adf.ts:143quoteNode/splitPath: the portable reader lives in parse/ and reaches back into portable/ - Shape:
src/markdown/emit/adf-to-markdown.ts:157spellPortableBlock: portable-only writing in a file whose name matches neither flavour - Locality:
src/markdown/emit/line-escaping.ts:260unspellableRuns: the 3am unit, concentrated escaping that needs spec §Canonical form and §Marks open to change safely
2026-10-14T13:01:12Z, PR #46 at 1e8fa26, against 06739b40b7
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | same | better |
| Inherited architect | better | better | same | better | better |
Mid A, decided by:
- Locality, Shape:
src/adf/inline-nodes.ts:37takesMark: the per-node mark types say which marks each node takes, and one predicate serves the parser and the emitter where each worked it out differently - Locality:
src/markdown/parse/directive-nodes.ts:138readNamedMark: the caller passes the message it wants instead of cutting text out of another module's message - Locality:
src/markdown/parse/markdown-to-adf.ts:280commonMarkSpellings: a new hand-kept table the parser must keep in step with the emitter'scommonMarkSpelling - Navigation:
src/markdown/emit/inline-line.ts:224carries: "withheld-mark" names the carry the same way as the corpus fixture and the decision index - Shape:
src/markdown/parse/inline-content.ts:405linkPiece: refusals name the fix, thoughmarksItemreturning true for a non-node and the hard-break carve-out read a little harder
Inherited architect, decided by:
- Navigation, Self-sufficiency:
README.md:455unsupported-node-shape: each cause sits beside its own remedy, grouped by direction, where one cell held them all - Locality, Self-sufficiency:
src/adf/inline-nodes.ts:37takesMark: one predicate and a per-type mark list replace a boolean read two ways by the parser and the emitter - Locality:
src/markdown/parse/directive-nodes.ts:137readNamedMark: the caller passes its message rather than editing another module's text - Locality:
src/markdown/parse/markdown-to-adf.ts:279commonMarkSpellings: a hand-kept list of the emitter's CommonMark spellings in another file, where the new version rots first - Shape:
src/markdown/parse/inline-content.ts:294marksItem: reads as a verb phrase and returns true for items no mark lands on - Locality:
src/markdown/parse/inline-content.ts:400linkPiece:linkTo's destination-ahead-of-hard-breaks branch is right only becauselinkPiecerefused every other unlinkable node first, and neither says so - Navigation:
MIGRATION.md:3From 0.2.0 to 0.3.0: a reader starting from a mark lost after upgrading finds a table and a fixture named after the cause
2026-10-14T13:02:45Z, PR #46 at 1e8fa26
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Junior A | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Mid A | 7 | 5 | 6 | 5 | 5.5 |
| Maintainability senior | 7 | 5.5 | 6.5 | 5.5 | 6 |
| Inherited architect | 6.5 | 6 | 5.5 | 7 | 6 |
| Mean | 6.88 | 5.50 | 6.13 | 5.75 | 5.88 |
Junior A, hardest first:
- Self-sufficiency, Overall:
src/markdown/emit/line-escaping.ts:230escapeClosedRuns/escapeClaims: three parallel per-character arrays and a backward-built set of backtick lengths, opaque without spec §Canonical form open - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: a memo filled by the parser and the portable reducer and drained by the walk, deleted on read - Locality:
src/markdown/parse/markdown-to-adf.ts:237splitPath: stand-in nodes and a re-run split to place an error path - Locality, Shape:
src/markdown/parse/inline-content.ts:449resolveNodes/pairedHighlights: placeholder text nodes until a highlight pairs, counters and in-place overwrites - Shape:
src/markdown/emit/inline-line.ts:82emitLine: a retry loop whose outcome also flows back into the parser
Mid A, hardest first:
- Locality, Overall:
src/markdown/parse/markdown-to-adf.ts:237splitPath: fake taskList and bulletList stand-ins and a probe node re-run through the split to name a path - Self-sufficiency:
src/markdown/emit/line-escaping.ts:230escapeClosedRuns: why a right-to-left walk suffices lives only in the spec - Locality:
src/markdown/parse/inline-content.ts:332closeBracket/truncatePieces: four sites mutatescan.piecesanddeactivatedBefore - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: filled from the parser and the portable reducer, the clearest action at a distance - Shape:
src/markdown/portable/inline-reduction.ts:194trimmedEdges: two fixpoint loops with no termination argument and a number-or-undefined edge depth
Maintainability senior, hardest first:
- Self-sufficiency, Overall:
src/markdown/emit/line-escaping.ts:142escapeClaims/unspellableRuns: three passes whose sufficiency no statement gives, and an opening-link signal read from segment structure - Locality:
src/markdown/parse/inline-content.ts:332closeBracket/resolveNodes:Scanmutated from about ten functions over a three-wayInlineunion - Locality:
src/markdown/parse/markdown-to-adf.ts:237splitPath: a local simulation of the task-list split, hard to convince oneself is right - Locality:
src/markdown/emit/adf-to-markdown.ts:127readableBlock: a reference-keyed memo filled across three directories - Shape:
src/markdown/portable/adf-to-portable-markdown.ts:59reduceToPortable: reruns the reduction on the raw document to get a refusal's path
Inherited architect, would restructure first:
- Navigation, Shape:
src/markdown/portable/conventions.ts:8Claims/flavourClaims: the switch for all three flavours filed under portable/ - Navigation:
src/markdown/parse/markdown-to-adf.ts:161quoteNode/splitPath: the portable reader lives in parse/ and the portable writer's spellings inemit/adf-to-markdown.ts:157spellPortableBlock - Locality:
src/markdown/parse/markdown-to-adf.ts:266directiveNode: the reader asks the writer'scommonMarkSpelling, and the writer reuses the reader's tokenizer, so neither side changes alone - Shape:
src/markdown/directive-syntax.ts:32Read: the general reader-failure type housed in the directive grammar file, among 15 loose files insrc/markdown/ - Shape:
src/markdown/emit/adf-to-markdown.ts:45writeMarkdown: writes both flavours in a file named for the lossless one
2026-10-14T19:06:43Z, PR #49 at d8fbff6fde, against 696aca1c71
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | same | same | better |
| Inherited architect | same | same | worse | same | same |
| Maintainability senior | same | better | same | same | better |
| Junior A | better | same | worse | same | better |
Mid A, decided by:
- Navigation, Locality:
src/adf/inline-nodes.ts:41takenMarkTypes/takesMark: the code-text rule lives in one predicate beside the mark table, reached by the parser, the emitter's carry and the portable reducer - Locality:
src/markdown/parse/inline-content.ts:584highlighted: asksmarksIteminstead of a hand-kept code check - Locality:
src/markdown/portable/inline-reduction.ts:136portableMarks: drops exactly the marks the reader refuses, by the shared name - Locality:
src/markdown/emit/inline-line.ts:103freshFallbacks:carriesno longer shows every reason a node is carried; the set starts pre-filled - Shape, Self-sufficiency:
src/adf/inline-nodes.ts:40takenMarkTypes:undefinedmeans every mark, explained only by its comment; spec says code text takes onlylink
Inherited architect, decided by:
- Shape, Locality:
src/markdown/emit/inline-line.ts:102freshFallbacks: seeds schema carries into a set named for fallbacks, andcarriesno longer says why a node is carried - Locality:
src/adf/inline-nodes.ts:5codeTextMarkTypes: holdscodewith nothing saying why, and spec/flavour.md says code text takes onlylink - Locality:
src/adf/inline-nodes.ts:46takesMark: the answer depends on the node's marks at call time, right only because a code span is built withcodefirst - Locality:
src/markdown/parse/inline-content.ts:584highlighted: one table now answers what two hand-written checks did
Maintainability senior, decided by:
- Locality, Overall:
src/adf/inline-nodes.ts:41takenMarkTypes/takesMark: one function states the code-text rule the parser and emitter both ask;undefinedmeaning every mark is visible only in its comment - Locality:
src/markdown/parse/inline-content.ts:587highlighted: routes throughmarksIteminstead of a private copy of a schema rule - Locality:
src/markdown/portable/inline-reduction.ts:146portableMarks: filters by the shared list, but checkscodeitself rather than askingtakesMark - Locality:
src/markdown/emit/inline-line.ts:103freshFallbacks:carriesis right only if the caller seeded the set, and its comment no longer names withheld marks
Junior A, decided by:
- Navigation, Overall:
src/adf/inline-nodes.ts:5codeTextMarkTypes: the code-text rule lives in one table beside the other inline nodes' table - Shape:
src/adf/inline-nodes.ts:41takenMarkTypes: "taken" reads as accepted or as already held, andundefinedmeans every mark - Shape:
src/markdown/emit/inline-line.ts:103freshFallbacks: named fresh but seeds the carried set, andcarries's comment no longer names the withheld-mark carry
2026-10-14T20:46:20Z, PR #53 at 787d909, against 498e874
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | better | same | better |
| Inherited architect | better | better | better | same | better |
Mid A, decided by:
- Shape:
src/markdown/emit/inline-line.ts:103withheldMarkFallbacks: renamed fromfreshFallbacks, it now says the fallbacks start seeded with every node holding a withheld mark - Locality:
src/markdown/emit/inline-line.ts:234carries: the comment now nameswithheldMarkFallbacksas where the withheld-mark carries are decided, linking the two units
Inherited architect, decided by:
- Locality, Navigation:
src/markdown/emit/inline-line.ts:234carries: the comment now points atwithheldMarkFallbacksfor the third kind of carry, a hidden dependence made followable - Shape, Navigation:
src/markdown/emit/inline-line.ts:103withheldMarkFallbacks: the old namefreshFallbackshid a pre-seeded set; the new one says what it holds - Shape:
src/markdown/portable/inline-reduction.ts:84mediaLeaves: three branches, two writing[alt](url)by different routes, seen only by readingportableMarks - Self-sufficiency:
src/markdown/portable/inline-reduction.ts:83mediaLeaves: the comment says why an inline image becomes a link, not why the other target goes in parentheses asimage
2026-10-22T19:35:21Z, PR #80 at ff220e6, against 2e06141
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | same | better |
| Inherited architect | better | better | better | same | better |
Mid A, decided by:
- Navigation, Shape:
src/markdown/portable/portable-markdown-to-adf.ts:22portableMarkdownToAdf: the portable reading has its own file, andparse/markdown-to-adf.tsshrinks from 394 to 267 lines - Navigation, Shape:
src/markdown/directive/syntax.ts:1directive/: ten directive files once spread over three directories share one folder - Navigation, Shape:
.oxlintrc.json:5overrides: lint enforces the layering, andparse/reachesemit/only throughspelling-questions.ts - Navigation, Shape:
src/markdown/flavour.ts:6Claims: the shared claims left a portable-named file for a neutral home - Locality:
src/markdown/portable/portable-markdown-to-adf.ts:102bulletBlocks/readTaskBlock: a refusal's path is found by one marker after the one split, not a replayed split on stand-ins - Locality:
src/markdown/emit/adf-to-markdown.ts:35SpelledBlock: a list's interruption and kind are fixed when spelled, not re-derived with a taskList special case - Locality:
src/markdown/commonmark/backtick-runs.ts:11backtickCloser: per-length cursors that needfromrising add hidden state (counterweight) - Shape:
src/markdown/emit/adf-to-markdown.ts:26FlavourBlockWriters/FlavourBlockReaders: the core now exports internals and a reader follows an injected function (counterweight)
Inherited architect, decided by:
- Locality, Shape:
src/markdown/parse/markdown-to-adf.ts:23FlavourBlockReaders/ReadAs: the core reader is flavour-neutral but for two hooks; the callback costs a search to find its supplier - Locality:
src/markdown/portable/portable-markdown-to-adf.ts:147readTaskBlock/bulletBlocks: one marker found by identity replacessplitPath's fake list;steps.slice(0, -2)still costs a re-read - Navigation, Shape:
src/markdown/flavour.ts:1Flavour/Claims/flavourClaims: what any flavour claims no longer lives in a portable-named file - Navigation, Shape:
src/markdown/directive/syntax.ts:1directive/: one folder answers where the directive grammar is - Navigation, Shape:
src/markdown/emit/spelling-questions.ts:1spelling-questions: the one parse→emit dependency is a named seam - Locality, Shape:
src/markdown/portable/block-spelling.ts:12portableBlockWriters: the emitter loses the portable spellings and re-derives no list facts; the portable file imports five emitter internals back - Locality:
src/markdown/commonmark/backtick-runs.ts:11backtickCloser: a closure correct only for risingfrom, stated not enforced (against) - Locality:
src/markdown/parse/blocks.ts:67Line.spaces/matchBlankLine: tab remainders in a separate field every site must remember (against) - Shape:
src/markdown/portable/portable-markdown-to-adf.ts:19expandBlockReaders/portableBlockReaders: a swapped reader object replaces theinExpandflag, less obvious on first read
2026-10-23T01:53:14Z, PR #82 at 8e7da0d, against 33e2a86
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | worse | same | worse |
| Inherited architect | same | worse | same | same | worse |
Mid A, decided by:
- Locality, Shape:
src/markdown/parse/inline-content.ts:264assemble: an (image) leaves a slot throughScanned.imageLinks, is dropped bylinkedAlt, regathered bylinkedImagesand kept apart byresolvedPieces; five functions and two recursion levels to follow one image - Locality:
src/markdown/parse/inline-content.ts:209directivePieces:inLinkholds only through mark slots, so the mark is read before the slot and a node directive silently resets it - Shape:
src/markdown/parse/inline-content.ts:58Piece: gainsImageLink,Scannedbecomes{ imageLinks, pieces }, andlinkedAltnow also discardsimageLinkpieces, which its name does not say - Shape:
src/markdown/mark-spellings.ts:58commonMarkLink: a sixth positional parameter,escapes, which the parser always passes as'lossless' - Locality:
src/markdown/portable/inline-reduction.ts:154portableLink: reads easier; it keeps the title and leaves escaping tospellTitle, andimageAsidebuilds the (image) once
Inherited architect, decided by:
- Locality:
src/markdown/parse/inline-content.ts:209directivePieces: each slot returns its nodes and a list of (image)s still to place, tracked through eight units, andinLink's narrowed meaning lives in one boolean expression - Locality:
src/markdown/emit/inline-line.ts:69tryPipeCell: the portable flavour skips the pipe check, its safety resting on three guards elsewhere, and the comment names the wrong file for half of it - Locality:
src/markdown/portable/inline-reduction.ts:154portableLink: reads easier; the reducer only normalizes and escaping stays inspellTitle
2026-10-26T12:16:45Z, PR #86 at fa00f09e18, against 61a5c073e9
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | same | same | better |
| Inherited architect | same | better | same | same | better |
Mid A, decided by:
- Locality, Navigation:
src/adf/shown-text.ts:60shownText: one switch per question says what each node shows, shared by the portable writer and the HTML carry, wherenodeLeavesworked it out inline - Locality:
src/adf/document.ts:53writableContent: every writer takes the shape, version and length checks from one function instead of repeating them - Navigation, Locality:
src/adf/plain-image.ts:19plainImage: one named predicate answers "is this the plain image" for both formats;tryImageshrinks to a lookup - Navigation:
src/length-bound.ts:4longestOutput: the file and the name now say the bound covers every writer - Navigation:
src/html/emit/adf-to-html.ts:21adfToHtml: a cold-findablehtml/emit/of small units named for one block kind each, its contract inspec/html.md - Shape:
src/markdown/mark-spellings.ts:40linkMark: seven small converters between three representations of one link;shownLinkandlinkAttrsdiffer only on a non-string title - Shape:
src/html/emit/carry-element.ts:13carriedBlock: reuses the namessrc/markdown/opaque-carry.tsexports, with other return types - Shape, Self-sufficiency:
src/html/emit/carry-element.ts:30shownBlocks: a stack walk withnullsentinels and a threadedcodefield needs its comment and a second read
Inherited architect, decided by:
- Locality, Overall:
src/adf/shown-text.ts:60shownText: what each node shows has one switch per question, shared by the portable writer and the HTML carry, where it was worked out inline innodeLeaves,cardLeavesandmediaLeaves - Locality, Overall:
src/adf/document.ts:53writableContent: every writer opens with one call instead of repeating the prologue - Locality:
.oxlintrc.json:6thesrc/adf/**andsrc/html/**import bans:adf/importing no format, and HTML and markdown not importing each other, is now machine-checked - Locality:
src/markdown/parse/inline-content.ts:387closeBracket: an explicit bracket stack matches CommonMark's algorithm where a backward scan anddeactivatedBeforedid - Shape:
src/markdown/mark-spellings.ts:40linkMark: two shapes for one link with converters both ways, andshownLinkreading a non-string title differently fromlinkAttrs - Shape:
src/adf/shown-text.ts:7isBlockNodeType: neither it noroneLineis about shown text; the renames tolongestOutputandplain-image.tsbalance it - Navigation:
src/html/emit/carry-element.ts:13carriedBlock: its name,tryImageandlinkedTextcollide with units insrc/markdown/, so a symbol search finds two homes - Self-sufficiency:
src/html/emit/carry-element.ts:30shownBlocks: the densest new unit, a stack withnullblock ends and an inheritedcode; its comments send a reader to the decision log wherespec/html.mdexplains it
2026-10-28T10:33:35Z, PR #88 at 207bf01, against 240c39a
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | worse | same | same |
| Inherited architect | better | worse | better | same | same |
Mid A, decided by:
- Locality:
src/html/block-elements.ts:27readListStart: each element's spelling now sits in a small file beside its reader (anchor-element.ts,image-element.ts,language-class.ts), where240c39akept them inside the emitter, so changing one spelling no longer means hunting for its inverse - Locality:
src/adf/carried-json.ts:24carriedValue: the markdown carry and the HTML carry share three named steps wherereadCarriedJsonparsed, bounded and validated inline;notAStringlikewise leavesmarkdown-to-adf.ts - Shape:
src/html/parse/html-to-adf.ts:248readItemLine: an item's line spreads acrossreadLineParagraph,partedLine,asFirstParagraphandformRefusals, with a nested ternary picking the refusal, in a file importing 20 modules - Shape, Self-sufficiency:
src/html/escaping.ts:14misspelling: four plainreplaceAllcalls became regexes built from an entity map, with a negative lookahead to rebuild in one's head - Self-sufficiency:
src/html/parse/carry-element.ts:14readCarry: the coupling tocarryContentis stated where it lives, sospec/html.mdneed not be open - Shape:
src/html/data-attributes.ts:26readDataAttributes: an optionalleadingparameter and aprevioussentinel onlynameFault's comment explains, and arespelldefault added tospellsCanonicalJson
Inherited architect, decided by:
- Locality:
src/html/parse/html-to-adf.ts:234readItem: the writer's list-item layout is copied as string literals into the reader, to change in lockstep withwriteItemin another directory;readParagraphfinds an item's first paragraph by order, and line 256 is one ternary of about 300 characters - Navigation, Shape:
src/html/anchor-element.ts:4anchorOpener: each element's spelling has a file named after the element with its inverse beside it, where240c39akept them in a file named for escaping - Shape:
src/html/emit/adf-to-html.ts:90listElement: tag names and the order check come fromblock-elements.tsinstead of inline literals, andreadListStartis defined by re-running the writer - Locality:
src/html/carry-content.ts:13carryContent: the writer and the reader's edit check share one function, its comment warning that a change breaks reading - Locality, Self-sufficiency:
src/html/data-attributes.ts:26readDataAttributes: aleadingparameter only<ol start>uses, with the hardest comments in the change to parse - Locality:
src/html/carry-attributes.ts:11carryJsonOffset: rebuilds the writer's start-tag prefix to place an error, correct only whilecarryAttributeswritesclassfirst - Shape:
src/adf/carried-json.ts:12BoundedJson: a type whose only job is to order three steps, arespellhook, and ten small root files insrc/html/
2026-10-28T18:08:02Z, PR #99 at fcc24ad, against 1530666
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | same | same | better |
| Inherited architect | same | better | same | better | better |
Mid A, decided by:
- Locality, Overall:
src/markdown/emit/line-escaping.ts:97readBack: the writer reads its escaped line back through the real reader instead of imitating its backtick, emphasis and bracket rules by hand inescapeClosedRuns,unspellableRunsandlastLinkClose - Locality:
src/markdown/inline-content.ts:103SharedScan: what a directive's content shares with the outer content is one named object, where the base spread it throughScanand picked it withPick - Locality:
src/markdown/commonmark/link-syntax.ts:55readInlineTarget: a mutable memo shared by every link target, filled lazily, where the base read a target as a pure function of its arguments - Self-sufficiency:
src/markdown/commonmark/link-syntax.ts:76destinationEnds: a stack-based table followed only through its long comment, though the base's equally opaqueescapeClosedRunsis gone - Shape, Navigation:
src/markdown/inline-content.ts:121parseInlineContent: moved out ofparse/now thatemit/uses it, and takesopeningLinkTakesDirectiveas an argument every caller passes the same
Inherited architect, decided by:
- Locality, Self-sufficiency:
src/markdown/emit/line-escaping.ts:97readBack: the writer checks its line throughreadLineBack, so a change to the reader's matching needs no mirror inemit/; thefaultedfallback still leans on its comment - Self-sufficiency:
src/markdown/emit/line-escaping.ts:136withTextEscapes: withtextOpeners, states the whole rule, where the base'sescapeClosedRunsand itsformedset needed the spec paragraph beside it - Locality:
src/markdown/emit/line-escaping.ts:271unspellableRuns: asks the reader's emphasis pairing instead of rebuilding delimiter runs and re-runningmatchEmphasis - Locality:
src/markdown/inline-content.ts:461resolveTarget: one target memo keyed by outermost offsets, shared throughscan.shared, brings offset arithmetic and a bounds check that depends on how the slot was cut - Self-sufficiency:
src/markdown/commonmark/link-syntax.ts:76destinationEnds: the densest new code, understandable only through its five-clause comment - Shape:
src/markdown/inline-content.ts:768parseInlineContent: takes the writer'sopeningLinkTakesDirectiveas a sixth parameter, and moved out ofparse/where a reader would look for it
2026-10-28T19:34:20Z, PR #100 at 222ad24, against 0003675
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | same | same |
| Inherited architect | better | same | same | same | same |
Inherited architect, decided by:
- Navigation:
README.md:730"Changing the source": names./ci.shand./mutation-tests/run.sh, what they need and what fails a run, where the base's README named neither
2026-10-29T15:41:57Z, PR #106 at 4246600, against c7bbb04
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | worse | worse | worse |
| Inherited architect | same | worse | worse | same | worse |
Mid A, decided by:
- Locality, Self-sufficiency:
src/markdown/emit/block-text.ts:56writtenText: prefixes recorded in a tree and applied later by a stack walk overopen,quotes,startedand'leave'sentinels, where the base'squotedandtryListItemLinesapplied them in place with split, map and join - Locality, Shape:
src/markdown/emit/block-text.ts:12Shape: eight cached measures kept in step by hand across four constructors, their arithmetic shown equal to the written text only in a test - Locality:
src/markdown/commonmark/grammar.ts:207holdsOnlyRuleCharacters: a grammar helper carries a contract owned by BlockText, standing in front ofisThematicBreak - Locality:
src/markdown/portable/block-spelling.ts:15claimsItem: amarkerOpeningfast path that must agree with two regexes, only a comment saying so - Shape, Locality:
src/markdown/emit/inline-line.ts:31FallbacksPerPass: a switch whose only second user is a test, threaded through five production functions and changingdroppedRuns - Self-sufficiency, Shape:
src/markdown/emit/line-escaping.ts:274unspellableRuns: the cascade throughgivesUpandmayFlankneeds CommonMark's flanking rules open beside it, where the base returned the first misread pair - Shape:
src/markdown/emit/inline-line.ts:94emitLine:linePass,takenThisPassandcheckedCarryadd two concepts to the fallback loop
Inherited architect, decided by:
- Locality, Shape:
src/markdown/emit/block-text.ts:56writtenText: a stack walk with a'leave'sentinel and eight hand-kept counters replaces string operations readable where they stood;prefixedTextwith an empty indent stretches its name - Locality:
src/markdown/portable/inline-reduction.ts:254droppedRuns: which runs drop in one pass is decided twice, bygivesUpin line-escaping and again bydropsAlone, in the code the 3am question lands in - Shape:
src/markdown/emit/inline-line.ts:31FallbacksPerPass: a test-only mode threaded through production signatures, its'first'reading not holding in inline-reduction's highlight drops;checkedCarryadds an ordering rule - Locality:
src/markdown/emit/adf-to-markdown.ts:310tryListItemLines: reads four measures defined inblock-text.tswhere the base checked strings in place - Locality:
src/markdown/commonmark/grammar.ts:206holdsOnlyRuleCharacters: the grammar module holds a rule that exists only for the emitter's BlockText - Locality:
src/markdown/portable/conventions.ts:5markerOpening: repeats the[the marker regexes encode
2026-10-30T11:10:42Z, PR #107 at 430310d, against 41fd106
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | worse | worse | worse |
| Inherited architect | same | worse | worse | worse | worse |
Mid A, decided by:
- Locality, Shape:
src/markdown/emit/line-escaping.ts:294unspellableRuns: a sweep over the sharedPairSweep.fallen, each verdict reading those settled before it, through helpers that call each other in a web, where the base's one loop calledgivesUp - Locality:
src/markdown/emit/line-escaping.ts:32RunFallback: the escaper models how each caller takes a run back, the portable reducer'sdropsAlonereaching it as thealonecallback, where the base's reducer chose its drops beside its leaves - Self-sufficiency:
src/markdown/emit/line-escaping.ts:344holdsAlike: its delimiter condition needs the delimiters' spellings known, and the sweep's rule rests on matching one run per pass, which only a property test shows - Shape:
src/markdown/emit/line-escaping.ts:65Standing:fallen,merging,pairAtandeitherare defined only by one-line comments that use further new terms
Inherited architect, decided by:
- Locality, Shape:
src/markdown/emit/line-escaping.ts:294unspellableRuns: settles pairs outward from the first misread pair, each verdict reading thefallenflags settled before it, so one pair's verdict needs the whole sweep's state, where the base's rule was one loop plusgivesUpand a four-linemayFlank - Shape, Locality:
src/markdown/emit/line-escaping.ts:337fallsWithFirst: calls run about five levels deep throughmayFlank,runEdge,pairSpellings,wordBesideandpairStanding, each taking the whole sweep;holdsAlike,holdsEarlier,spansAlikeandStandingneed their comments, andpairStanding's rule is asserted with no derivation - Locality:
src/markdown/portable/inline-reduction.ts:223spellableLine: passesdropsAloneas a callback through four functions into the escaper'smerging, splitting one contract across two files - Locality:
src/markdown/portable/inline-reduction.ts:244withoutMarks: runs may now nest, for a reason that lives in the escaper's sweep - Self-sufficiency:
src/markdown/emit/line-escaping.ts:336fallsWithFirst: its rule is equivalence to the'first'mode, checked only by a property test, andrunEdgeandwordBesideneed CommonMark's delimiter-run rules beside the code
2026-10-31T01:31:04Z, PR #110 at ceebcfb, against e743868
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | worse | better |
| Inherited architect | better | better | better | worse | better |
Mid A, decided by:
- Navigation, Shape:
src/markdown/emit/unspellable-runs.ts:33unspellableRuns: the emphasis-run sweep has its own file; line-escaping.ts holds only escaping - Locality, Shape:
src/markdown/emit/unspellable-runs.ts:9RunFallback: the drop fallback carries nodes, and dropsAlone sits beside its only consumer - Shape:
src/markdown/emit/unspellable-runs.ts:30Standing: four named states and sharedtouchingreplace a bare undefined and two hand-rolled walks - Locality, Shape:
src/markdown/emit/inline-line.ts:268emitLeaf: leaf spellers return segments, and one place builds and checks every carry - Locality:
src/markdown/emit/block-text.ts:58holdsBlankLine: callers ask BlockText instead of combining flat fields - Self-sufficiency:
src/markdown/emit/unspellable-runs.ts:208pairStanding: the reasoning moved to the decision log, so its branches cannot be checked without it open - Self-sufficiency:
src/markdown/emit/inline-line.ts:48readBackPasses: the 32-pass cap and its carry-all fallback are justified only by a pointer to the decision log
Inherited architect, decided by:
- Navigation, Shape:
src/markdown/emit/unspellable-runs.ts:33unspellableRuns: a mark gone after a round trip now leads to a file whose name says so - Locality:
src/markdown/portable/inline-reduction.ts:228spellableLine: no closure into the portable reducer's dropsAlone from deep in the emitter - Locality, Shape:
src/markdown/emit/inline-line.ts:53emitInlineLine: the test-only perPass knob is gone from production signatures, at the price of exports only a test uses - Shape:
src/markdown/emit/unspellable-runs.ts:191touching: one shared walk, and truer names such as holdsPairBefore and mergingEnds - Shape:
src/markdown/emit/block-text.ts:13FirstLine: eight flat fields became two grouped records with named predicates - Self-sufficiency:
src/markdown/emit/unspellable-runs.ts:208pairStanding: five branches whose proof now lives in the decision log - Self-sufficiency, Locality:
src/markdown/emit/inline-line.ts:48readBackPasses: a magic cap of 32 shared by two retry loops that must agree on giving up
2026-10-31T02:06:38Z, PR #111 at b067b88, against de0033c
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | same | better | better |
| Inherited architect | same | same | better | same | better |
Mid A, decided by:
- Self-sufficiency, Overall:
src/adf/inline-nodes.ts:42takenMarkTypes: text takes a named list, so the marks it takes read without the schema open - Locality:
src/markdown/emit/inline-line.ts:65portableLineFallback: one guard covers both the seeded carries and the emission's
Inherited architect, decided by:
- Shape, Overall:
src/adf/inline-nodes.ts:42takenMarkTypes:undefinednow means only a node type outside the tables - Shape:
src/markdown/inline-content.ts:261directiveMarkPieces: this caller overridesmarksItem's rule that a non-node is markable, with nothing at the call site saying why
2026-11-03T21:09:33Z, PR #116 at 9e8df99, against 8bcf4a5
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | worse | better | better |
| Inherited architect | same | better | worse | better | better |
Mid A, decided by:
- Locality, Overall:
src/markdown/mark-spellings.ts:48insideRun. What counts as "in the same run" is now one function, used by the emitter and the reducer, and its comment names the footgun; at the base the two compared marks separately and nothing said they had to agree. - Locality:
src/markdown/portable/inline-reduction.ts:221sharedRuns. The reducer no longer depends on a comparator exported from the editor-normal module, which made a reader check whether normalization mattered here. - Self-sufficiency, Overall:
src/markdown/portable/inline-reduction.ts:231spellableLineandsrc/markdown/portable/inline-reduction.ts:165trimmedEdges. Both loops now state in one line why they terminate. - Self-sufficiency:
src/markdown/portable/inline-reduction.ts:262withoutMarkswithmarkCount. A pass that takes no mark returnsundefinedandwithoutFallbackrefuses it, so the argument is enforced in the code. - Shape:
src/markdown/mark-spellings.ts:21RunNode, threaded throughsrc/markdown/emit/inline-line.ts:213emitRunandsrc/markdown/emit/inline-line.ts:232inlineRuns.outeranddepthalways hold the same value, and a reader has to trace the recursion to answer why both exist. - Shape:
src/markdown/emit/inline-line.ts:384tryLinkagainstsrc/markdown/emit/inline-line.ts:364codeSpans. The same count is spelled two ways a few lines apart. - Shape:
src/markdown/emit/inline-line.ts:288carriedRunwithlineNodesinInlineContext. Nodes and range can no longer disagree, but the context gains a field only this function uses. - Locality:
src/markdown/portable/inline-reduction.ts:250withoutOpeningLinkCode. AfindIndexover the run says what it means, where the base wrapped one mark in an array to reuse a helper.
Inherited architect, decided by:
- Locality, Self-sufficiency:
src/markdown/portable/inline-reduction.ts:262withoutMarks, withmarkCountat:278and the comment at:231inspellableLine. A pass that takes no mark returnsundefinedandwithoutFallbackrefuses it, so the termination claim can be checked in this file. - Locality:
src/markdown/mark-spellings.ts:48insideRun. The rule for what stays in a run has one home, used by the writer'sinlineRunsand by the reducer, where the base left a reader to prove two comparators agreed on reduced marks. - Shape, Locality:
src/markdown/portable/editor-normal.ts:11joinsWhenEditorNormal.sameMarkWhenEditorNormalis gone, so the file now only answers what the editor joins and normalizes. - Shape:
src/markdown/emit/inline-line.ts:213emitRun. It carriesdepthand a per-nodeRunNode.outerthat are always equal, and a reader has to trace every path to learn that, because nothing in this version needs a per-node count. - Shape:
src/markdown/emit/inline-line.ts:384tryLink, against:368incodeSpans. Two sources for one number sit in the same file, where the base useddepth + 1in both. - Locality:
src/markdown/emit/inline-line.ts:288carriedRun, withlineNodesat:37. The nodes are sliced from a new context field byrange, sorangemust be line-absolute; a small cost against the Locality gains. - Shape:
src/markdown/portable/inline-reduction.ts:247withoutOpeningLinkCode.findIndexwithinsideRunand anendbound reads directly as the opening link's run; a real gain, smaller than thedepthandoutercost. - Shape:
src/markdown/portable/inline-reduction.ts:221sharedRuns. A seven-line walk threads aRunNodewhere the depth is already the loop index, replacing a two-linewhile; it uses the shared rule but reads no easier. - Self-sufficiency:
src/markdown/portable/inline-reduction.ts:165trimmedEdges. The new comment names the termination measure: whitespace or marks per character, which merging never adds. - Self-sufficiency:
src/markdown/mark-spellings.ts:20RunNodeand:47insideRun. The comments pay for the file's extra concept, thoughnodeMarks(node)[outer]atinline-line.ts:238now needs a jump to another file, andsrc/markdown/portable/inline-reduction.test.ts:39has a stray comment above an unrelated test.
2026-10-31T03:20:46Z, PR #112 at 66ad0be, against 8bcf4a5
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | same | same | worse |
| Inherited architect | same | worse | same | same | worse |
Mid A, decided by:
- Locality:
src/markdown/emit/skipped-nodes.ts:15spanRuns: a second copy ofinlineRuns' run grouping, kept in step only by a comment, editingspannedin place while it recurses - Locality:
src/markdown/portable/inline-reduction.ts:169trimmedEdges: reads each leaf's neighbours from a parallel spanned array, so the portable edge rule depends on the writer's spanning - Locality:
src/markdown/emit/inline-line.ts:119spannedLine: every pass emits a second, spanned line first and throws it away on a fallback or a portable!adf: - Locality:
src/markdown/emit/skipped-nodes.ts:54holdsEmptyMarks: a one-line exception at the end of a predicate decides whether a node is lent a mark
Inherited architect, decided by:
- Locality:
src/markdown/emit/skipped-nodes.ts:16spanRuns: run grouping in two places that must agree, linked only by a comment naminginlineRuns - Locality:
src/markdown/portable/inline-reduction.ts:169trimmedEdges: models the writer as always spanning, whichspannedLinedoes only where the line reads back - Locality:
src/markdown/emit/inline-line.ts:119spannedLine: refuses a portable span by the!adf:prefix of a segment's text, and turns every emission failure into the parted line - Locality:
src/markdown/emit/skipped-nodes.ts:11spanSkippedNodes: signals nothing spanned by returning the same array, and hides the empty-marks exception from the caller
2026-10-31T07:18:17Z, PR #112 at d554e22, against 8bcf4a5
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | worse | same | worse |
| Inherited architect | same | worse | worse | same | worse |
Mid A, decided by:
- Locality, Shape:
src/markdown/emit/inline-line.ts:246inlineRuns: aspansflag switches it between two modes, and a mutablespanEndset byspannedTolets one iteration steer later ones - Shape:
src/markdown/emit/inline-line.ts:230emitRun: picks the behaviour with a bare positionalfalse, aslendMarksdoes withtrue - Locality:
src/markdown/emit/inline-line.ts:291spannedNodes: decides whether anything spanned by object identity, which holds only becauselendMarkspushes originals and onlywithMarkcopies - Locality:
src/markdown/emit/inline-line.ts:108linePass: tries the spanned line first and falls back to the parted line, andspannedLineturns every refusal into a quietundefined - Locality:
src/markdown/portable/inline-reduction.ts:168trimmedEdges: judges edge whitespace against the emitter'sspannedNodes, so the portable trimming depends on the writer's span rule - Shape:
src/markdown/emit/inline-line.ts:270spannedTo: one of four new units in a file grown from 390 to 451 lines
Inherited architect, decided by:
- Locality:
src/markdown/emit/inline-line.ts:108linePass: each pass emits two candidate lines, and nothing records which one was written - Locality:
src/markdown/portable/inline-reduction.ts:168trimmedEdges: imports the emitter'sspannedNodeswith a fresh carried set, so its verdict and the written line can be judged on different node lists - Shape:
src/markdown/emit/inline-line.ts:246inlineRuns: one function serves two callers through a boolean thatemitRunalways passes asfalse, plus a lookahead cursor - Shape:
src/markdown/emit/inline-line.ts:271spannedTo: returnsstartto mean "spans nothing", a sentinel its name does not state, besidespansNode's five-condition expression
2026-11-03T14:18:32Z, PR #112 at 63e3eb2, against 8bcf4a5
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | worse | worse | worse |
| Inherited architect | same | worse | same | same | worse |
Mid A, decided by:
- Locality, Self-sufficiency:
src/markdown/portable/inline-reduction.ts:164trimmedEdges: indexes the emitter's spanned nodes besidemerged, relying on one output node per input in order, and on the emitter writing the spanned line - Locality, Shape:
src/markdown/emit/inline-line.ts:288spannedRuns: reports a span through the mutablespanned.spans, set deep in the recursion, while splicing and rewritingopen.nodesin place - Shape, Locality:
src/markdown/emit/inline-line.ts:113linePass: tries the spanned line then the parted one, andspannedLineRefusal's reasons are a distinction its caller never uses - Self-sufficiency:
src/markdown/emit/inline-line.ts:315spansNode: maps ontotakesMarkonly after a hop totakenMarkTypes
Inherited architect, decided by:
- Locality:
src/markdown/portable/inline-reduction.ts:168trimmedEdges: readsspanned[index ± 1]besidemerged[index], a same-length contract neither end states - Locality:
src/markdown/emit/inline-line.ts:69portableLineFallback: the reducer judges the parted line whilelinePasswrites the spanned one, so the line judged is no longer the line written - Locality:
src/markdown/emit/inline-line.ts:113linePass: each pass builds, emits and may discard a rewritten node list, a second path to suspect for a mark gone
2026-11-03T21:46:31Z, PR #112 at f7b8e45, against 0166a71
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | worse | same | worse |
| Inherited architect | same | worse | worse | worse | worse |
Mid A, decided by:
- Locality, Overall:
src/markdown/emit/line-escaping.ts:22MarkRun.depthused to be an unconditional index into each node's marks. It now means that only "on a parted line", sowithoutMarks(src/markdown/portable/inline-reduction.ts:257) andendsAlone(src/markdown/emit/unspellable-runs.ts:94) are correct only because of which line they were handed, and neither shows that at its use. - Locality:
src/markdown/emit/inline-line.ts:71portableLineFallback. The barefalseargument is what upholds thatdepthcondition, and the reason sits in another file.linePasstriestruefirst and the reducer's counts usespans: true, so a reader must keep track of which walk each caller gets. - Locality, Shape, Overall:
src/markdown/emit/inline-line.ts:113linePass. One straight walk became two attempts with a preference. Its helperwritesSpannedinfers edge whitespace from a!adf:prefix on a syntax segment, so the reader has to work out why that prefix check means whitespace. - Locality, Shape:
src/markdown/emit/inline-line.ts:282runsSharedWithNext. WithcountSharedRuns, this is a second recursive walk that the reducer must trust to mirroremitRun. It uses an empty carried set, returns silently pastlargestNesting, and adds to the emit file's exports. - Shape:
src/markdown/emit/inline-line.ts:247inlineRuns. The base's simple append loop became an offset-skipping loop plusnodesInRun, which walks past holders and then slices back to them. It reads as correct, but it takes more to follow. - Shape:
src/markdown/portable/inline-reduction.ts:199leafEdges. The neighbour nodes gave way tonumber | undefinedcounts, where undefined means a line edge. They come from thesharedarray, whichtrimmedEdgesindexes by position, and this is less direct than asking about the neighbour itself. - Shape:
src/markdown/emit/inline-line.ts:40InlineContext.spans.spansis a boolean here, but inemitMarkedRunit holds the result ofcodeSpans(nodes), so the name tells a reader less than it should. - Locality:
src/markdown/portable/inline-reduction.ts:168trimmedEdges. This one reads better. The reducer asks the emitter's own grouping instead of the base's parallelsharedRunsand its warning comment, so the two can't disagree on what a run is. It offsets part of the cost but doesn't flip the ruling. - Shape:
src/markdown/emit/inline-line.ts:430tryLink. This also reads better, sincenodes[0]?.outer ?? 0says what the link's nodes hold where the base'sdepth + 1assumed it. It is too small to move the ruling.
Inherited architect, decided by:
- Locality, Self-sufficiency:
src/markdown/emit/inline-line.ts:71portableLineFallback, together withsrc/markdown/emit/inline-line.ts:115linePassandsrc/markdown/portable/inline-reduction.ts:168trimmedEdges. The reducer now trims edges by the spanned grouping and judges fallbacks on the parted line, and the writer then prefers the spanned line, so three steps read two different lines. For**Run `npm ci` first**the parted line traces as misflanked andstrongshould drop, and onlyadf-to-portable-markdown.test.ts:426showed otherwise: it survives becauseemitEmphasisspells the kept edge space as!adf:text, in a portable verdict line whose directive the portable writer would never emit, and no comment states this. - Locality:
src/markdown/emit/inline-line.ts:267nodesInRun, withsrc/markdown/emit/line-escaping.ts:22MarkRun. In the base, aRunNode'souteralways equalled the walk'sdepth, anddepthwas always an index into a node's marks; nowMarkRun.depthis a mark index only on a parted line.withoutMarkstrusts that index, and it holds only becauselinePassandportableLineFallbackboth route fallbacks through the parted attempt, in another file.tryLink'snodes[0]?.outer ?? 0is safe only if the first node is always a holder, which the reader has to derive. - Locality, Shape:
src/markdown/portable/inline-reduction.ts:218edgeDepth, withsrc/markdown/emit/inline-line.ts:282runsSharedWithNext. The base's localsharedRunsis gone, a real gain because the grouping now lives in one place. The replacement is a second recursive walk in the emitter,countSharedRuns, which returns silently pastlargestNestingwhereemitRunrefuses; its result is a count of runs, yetedgeDepthuses it as an index into the leaf's marks, and nothing says why the two agree on a spanned line. - Shape:
src/markdown/emit/inline-line.ts:40InlineContext.spansandspansLinessit on adjacent lines and mean unrelated things: a run across nodes, and a hard break across lines.spansalso means code spans atemitMarkedRunand atinline-reduction.ts:248, whilerunSpansandcodeSpansread as siblings, and the new boolean is passed bare at its call sites. - Shape:
src/markdown/emit/inline-line.ts:247inlineRuns. The base grew the previous run in place in one loop. The new version uses anextskip cursor, a helper that overshoots, andinside.slice(0, holders)to take back trailing spanned nodes; the rule is sound and a comment explains it, but it takes longer to verify.RunGroupingis satisfied structurally by passing the wholeInlineContext. - Self-sufficiency:
spec/flavour.md:568section Marks, read againstsrc/markdown/emit/inline-line.ts:115linePassandwritesSpanned. 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:49insideRun. 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 onrunsSharedWithNextcarries 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:129takeFallback. The first call ignores the fallback it was handed and only flipsparted, 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:264judgedLine. The reducer now mirrors the writer's spanned-then-parted order and judges two differently trimmed lines. It returns the partedleavesbecause the fallback's indexes only fit that line, sospellableLineandwithoutFallbackmust keep the two paired. At basespellableLine(line 230) judged and fixed the onecurrentline. - Locality:
src/markdown/portable/inline-reduction.ts:202runsSharedWithNext, read withleafEdgesat line 222 andedgeDepthat line 241. Trimming a leaf's whitespace now needs a run walk over the whole line, delivered through an index-parallelsharedarray read asshared[index - 1]andshared[index]. At basesharedRuns(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 withoutinlineRuns. - Locality:
src/markdown/emit/inline-runs.ts:32inlineRuns, read withrunEndat line 38. A run is now found by lookahead with anendskip, and crossed nodes keep theirouterthroughinsideRun(...) ?? runNode. Soouterno longer tracksdepthinemitRun, andtryLinkmust readnodes[0]?.outer. At base (src/markdown/emit/inline-line.ts:232) a run was built by appending to the previous one, andouterwas alwaysdepth + 1inside a run. - Navigation, Shape:
src/markdown/emit/inline-runs.ts:19inlineRuns. Run grouping,RunNode,insideRunandcarriesnow share one file named for what it holds, and writer and reducer both ask it. At base they were split between a private function ininline-line.tsandmark-spellings.ts, which held run concepts in a file about spellings, plus the reducer's ownsharedRuns. - Shape:
src/markdown/emit/line-escaping.ts:23MarkRun. A run now names itsmarkwhere it nameddepth, a positional index into each node's marks.withoutMarks(src/markdown/portable/inline-reduction.ts:294) andendsAlone(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:129takeFallback: the first fallback it is handed is thrown away and only setsparted, so a reader must already know that a verdict on the spanned line says nothing about what the parted line needs. In0166a71each call took what it was given. The loop inemitLinenow also starts at pass 0 (:97), andreadBackPassescounts past it, which adds more order to keep in mind. - Locality, Overall:
src/markdown/portable/inline-reduction.ts:264judgedLine: 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 whileemitLinekeepspartedset once flipped, an asymmetry the reader has to reconcile. In0166a71spellableLinemade one fallback call on the current line. - Locality:
src/markdown/portable/inline-reduction.ts:241edgeDepth, withrunsSharedWithNext(:202) andcountSharedRuns(:209): in0166a71sharedRunsanswered 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 throughtrimmedEdges. Reading it as "outermost marks" rests on the invariant stated in the comment atedgeDepth. - Navigation, Shape:
src/markdown/emit/inline-runs.ts:19inlineRuns: "why did this run group so" now has one named file, shared by the writer and the reducer. In0166a71the grouping was private toinline-line.ts, andinsideRunsat inmark-spellings.ts, a file about spellings.inline-line.tsis lighter for it, thoughcarriesat :61 stretches the new file's name a little. - Shape:
src/markdown/emit/line-escaping.ts:23MarkRun: it holds the mark itself where0166a71held adepthindex, and that index would be wrong once a run crosses nodes.withoutMarks(inline-reduction.ts:294) andendsAlone(unspellable-runs.ts:94) now read as what they do. This outweighs a smaller cost:depthinemitRunandouterinRunNodenow mean different things.
2026-11-04T12:16:56Z, PR #112 at eb92f94, against 0166a71
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | same | better | same | better |
| Inherited architect | better | same | better | same | better |
Mid A, decided by:
- Navigation, Shape, Overall:
src/markdown/emit/inline-runs.ts:18inlineRuns. Run grouping now has its own truthfully named file, holding the walk, the crossing rule and the shared-run count. At base the walk sat insideinline-line.ts, andinsideRunandRunNodesat inmark-spellings.ts, a module about spellings, so a run-grouping symptom now leads to one file. - Shape, Overall:
src/markdown/emit/line-escaping.ts:23MarkRun. A run now names the mark it spells, sowithoutMarks(src/markdown/portable/inline-reduction.ts:278) andendsAlone(src/markdown/emit/unspellable-runs.ts:94) read directly. The base'sdepthindex needed a comment and a matching index filter to say the same thing. - Shape, Overall:
src/markdown/emit/inline-line.ts:262emitLeaf. It takes aPlainRunwhosecarriedis decided once per node inlineSegments. The base askedcarries(node, carried, index)from three sites and threadedcarriedthroughInlineContext. - Shape:
src/markdown/portable/inline-reduction.ts:248judgedLine. The counterweight, narrowing the gain without cancelling it: it repeatsemitLine's spanned-then-parted order, its fallback indexes name the parted line, which only a comment explains, andrunsSharedWithNextlives inemit/but serves only the reducer.
Inherited architect, decided by:
- Navigation, Shape, Overall:
src/markdown/emit/inline-runs.ts:18inlineRuns. Run grouping now has one home, named for what it holds, so a symptom about a mark split or opened twice leads straight there. At base the same logic sat atinline-line.ts:232, in the middle of the line writer, withRunNodeandinsideRunin a file about spellings. - Shape:
src/markdown/mark-spellings.ts:32markSpelling. The file now holds only spellings, so its name tells the truth. The base also kept the run type andinsideRunthere. - Shape:
src/markdown/emit/line-escaping.ts:23MarkRun. A run now names its mark instead of an array index. This reads truthfully atwithoutMarks(src/markdown/portable/inline-reduction.ts:278), and a reader no longer has to work out what adepthindexes into.
2026-11-04T13:11:07Z, PR #117 at 283cf91, against d5d594b
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | same | same |
| Inherited architect | same | same | worse | same | same |
Inherited architect, decided by:
- Shape:
src/html/node-element.ts:9NodeElement.textAttribute. Leaving itundefinedmarks the row as a date, which the type doesn't say; emit and parse both readundefinedas "derive the text fromtimestamp", and the four rows are built three ways. - Shape:
src/html/parse/node-element.ts:36mismatch. It picks its message frommodel.leading(datetimefor a date,hreffor a card) in place of the node type, andreadNodeElementchecks all four kinds in one condition, so a reader works out which checks apply to which kind.
2026-11-04T15:59:34Z, PR #119 at 65f1c2a, against 13a2689
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | same | better | better |
| Inherited architect | better | better | same | better | better |
Mid A, decided by:
- Locality:
src/html/node-element.ts:19nodeElements: each inline node's element, shown text, leading attribute and mismatch message sit in one entry, where the base spread the date, text and card cases over three places - Locality:
src/html/parse/node-element.ts:24readNodeElement: one generic check runs the writer's ownshownandleading.valueover the node it built, where the base special-cased the date and branched on the leading name for its message - Self-sufficiency:
src/html/node-element.ts:7NodeElement: the type's comment states the contract, so a cold reader sees why the reader is safe without opening the spec - Shape:
src/html/node-element.ts:50card: dense early returns,hrefis undefined exactly when a card holds bothdataandurl; the type grew from five fields to eight - Shape:
src/html/node-element.ts:62textElement: hardcodes'text'whileinlineNodesinsrc/adf/inline-nodes.ts:16still declarestextAttribute: 'text', a second source for one fact
Inherited architect, decided by:
- Locality, Navigation:
src/html/parse/node-element.ts:24readNodeElement: one check built onmodel.build,model.shownandmodel.leading.valueholds for every node type, where the base'smismatchswitched on the leading attribute's kind - Locality, Self-sufficiency:
src/html/node-element.ts:31inlineCard: the card takes ADF's own vocabulary andcardat:50says why a card holding bothdataandurlrides the carry, where the base pointed attodo.mditem 133 - Locality, Navigation:
src/html/emit/node-element.ts:7nodeElement: the date, card and text rules live in one table, so a symptom about one node type leads to one entry - Shape:
src/html/node-element.ts:8NodeElement: the record grew from five fields to eight, three of them functions, behind a dense one-line contract comment, and the card'sbuildaddsurlonly whendatais absent
2026-11-04T18:58:37Z, PR #120 at 755241d, against 81d741d
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | same | same |
| Inherited architect | same | worse | same | worse | worse |
| Maintainability senior | same | worse | same | same | same |
| Junior A | same | worse | same | same | same |
Inherited architect, decided by:
- Locality:
src/html/emit/inline.ts:15inlineHtml: whether a linked card is refused depends on whether its enclosing block rides the carry, whichsrc/html/emit/adf-to-html.ts:123tryLeafBlockdecides far from this file - Self-sufficiency:
src/html/emit/inline.ts:15inlineHtml: the comment gave "HTML nests no link in a link" as the reason, which the carry's single link refutes; since fixed to name the schema - Self-sufficiency, Locality:
spec/html.md:130the carry rule: the exception sits beside the lossless markdown writer, which carries the same shape
Maintainability senior, decided by:
- Locality:
src/html/emit/inline.ts:15inlineHtml: whether a linked card is refused or carried depends ontryLeafBlockandinlineElementinsrc/html/emit/adf-to-html.ts:122, so changing which paragraphs ride the carry changes which documents are refused
Junior A, decided by:
- Locality:
src/html/emit/inline.ts:15inlineHtml: the card refusal fires only where the block around the card is written as an element, andinlineElementatsrc/html/emit/adf-to-html.ts:131decides that first, where the base's loop decided each node from the node alone
2026-11-04T19:35:07Z, PR #121 at 78ca66b, against 30f45b7
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | same | same | better |
| Inherited architect | same | better | same | same | better |
Mid A, decided by:
- Locality:
src/adf/document.ts:151refusedShape: one walk refuses the card for every writer and, throughcarriedNode, both carry readers, where the base held the rule in the HTML emitter alone - Locality:
src/html/emit/inline.ts:11inlineHtml: its loop no longer opens with a check whose comment relied on which callers reach it
Inherited architect, decided by:
- Locality:
src/adf/document.ts:151refusedShape: the rule against a link-marked card lives in one walk that every writer and both carry readers pass through - Locality:
src/html/emit/inline.ts:15inlineHtml: the base held the check at the top of the HTML writer's inline loop, with a comment about callers elsewhere
2026-11-08T21:12:40Z, PR #139 at 75606ad, against acc6df4
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | better | better | better | same | better |
| Inherited architect | same | better | better | same | better |
Mid A, decided by:
- Locality, Shape, Overall:
src/html/carry-content.ts:21shownBlocks: one BlockPart compared by reference replaces null sentinels and a mutable current record - Locality, Shape, Overall:
src/markdown/emit/adf-to-markdown.ts:135spellingMemo: ask and take hold the keep-or-drop rule in one closure, and the caller flag is gone - Locality, Navigation, Overall:
src/adf/document.ts:174shapeRefusal: one walk refuses every bad shape, where three files did - Locality, Overall:
src/html/data-attributes.ts:42readDataAttributesAfter: the leading-attribute case leavesnameFaultand its hidden invariant - Locality, Shape:
src/html/parse/html-to-adf.ts:105readBlocks: table state threads through the block loop, which reads harder than before - Shape:
src/markdown/emit/unspellable-runs.ts:30Verdict: one named verdict per pair replaces a Uint8Array and a separate set - Shape:
src/markdown/mark-spellings.ts:70commonMarkLink: a named LinkSurroundings object replaces three positional parameters - Navigation, Shape:
src/html/cell-element.ts:22cellAttributes: table-cell attributes are written and read in one file named for them
Inherited architect, decided by:
- Locality, Shape, Overall:
src/markdown/portable/adf-to-portable-markdown.ts:61reduceToPortable: a refusal's path comes from a source map, so no second run on the raw document - Locality, Overall:
src/adf/document.ts:174shapeRefusal: schema shape refusals live in one function in the first step - Locality, Shape, Overall:
src/html/carry-content.ts:21shownBlocks: no sentinel to hold in mind - Shape:
src/markdown/portable/inline-reduction.ts:242edgeOutcome: a tagged union says what the result means, whereundefineddid not - Locality, Shape:
src/html/data-attributes.ts:42readDataAttributesAfter: its own entry point for the leading attribute, chosen openly by the callers - Shape:
src/adf/block-nodes.ts:1isHeadingLevel: one source for the 1 to 6 range - Locality:
src/html/parse/html-to-adf.ts:95readBlocks: RowStep,closerOfand the close loop have to be pieced together to follow table state - Self-sufficiency:
src/html/parse/html-to-adf.ts:273readTable: the thead and tbody branches advance by one length that holds only because both strings are equally long
2026-11-08T22:07:58Z, PR #140 at 27e212c, against b3d136d
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | same | same |
| Inherited architect | same | same | same | same | same |
2026-11-08T23:20:43Z, PR #141 at 883fe80, against 2766a0a
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | same | same |
| Inherited architect | same | same | worse | better | same |
Inherited architect, decided by:
- Shape:
src/markdown/portable/portable-markdown-to-adf.test.ts:245refuses what a callout title or body holds that no node spells, at the path of the paragraph or the callout: a third localrefusedhelper, in two variants, beside the ones at :184 and :268 - Shape:
src/markdown/portable/adf-to-portable-markdown.test.ts:514writes a task list nested in the task before it, and more than one beside each other in that task: repeats task-list spellings the existing test at :141 pins, in two places that do not point to each other - Shape:
src/markdown/portable/portable-markdown-to-adf.test.ts:278reads a task whose marker line holds only breaks and spaces by the lines after it: its first assertion has text on the marker line, so the name does not describe it - Self-sufficiency:
src/markdown/portable/portable-markdown-to-adf.test.ts:232keeps the target of a link in a title whichever marks sit beside the link: worked input-to-output examples where a reader needed spec/flavour.md open beside the code - Self-sufficiency:
src/markdown/portable/adf-to-portable-markdown.test.ts:495writes a task list nested to the deepest level the reader carries, and refuses one more at the item holding it: shows in one place that the writer's depth limit lines up with the reader's
2026-11-09T00:23:10Z, PR #143 at 9a8f8b3, against 47b95fb
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | better | better | better |
| Inherited architect | same | better | better | better | better |
Mid A, decided by:
- Locality, Shape:
src/markdown/inline-content.ts:518markedNodes: the steps are calculations now; one array no longer rewritten in place by three steps that each rely on the shape the last left - Self-sufficiency, Locality:
src/markdown/inline-content.ts:551pieceNodes:==is its literal text at once, where the placeholder's life cycle spanned three functions and a comment - Shape:
src/markdown/inline-content.ts:595pairingMarks: the name says it returns marks, wheremarkPairingsmutatednodesand returned a boolean - Locality:
src/markdown/inline-content.ts:626highlightDelimiters: readsmarks[index]directly and counts every piece's text alike, with no holder special case
Inherited architect, decided by:
- Locality, Self-sufficiency:
src/markdown/inline-content.ts:518markedNodes: marks are computed first as plain data and highlights pair on them, so no placeholder's life cycle is held in mind across three steps - Locality, Shape:
src/markdown/inline-content.ts:595pairingMarks: pure, returns each piece's marks orundefinedon the refusal, wheremarkPairingsrewrotenodesand returned a boolean - Shape, Self-sufficiency:
src/markdown/inline-content.ts:626highlightDelimiters:holderbecomesmarksand the position special case is gone - Self-sufficiency:
src/markdown/inline-content.ts:550pieceNodes: its comment says what the delimiter is, where it explained a trick
2026-11-09T00:53:30Z, PR #144 at f822c57519, against 19c1a53dcc
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | better | better | same | better |
| Inherited architect | same | better | same | same | better |
Mid A, decided by:
- Locality, Shape:
src/markdown/inline-content.ts:425closeBracket: it reads the scan and returns aClosing; the base changed the scan at four points as it went - Locality:
src/markdown/inline-content.ts:438applyClosing: every change a]makes to the scan sits in one function, andlinkOpenersFromis one expression where the base wrote it twice - Shape:
src/markdown/inline-content.ts:421Closing: a two-arm type replacespopBracket,literalCloseandunopened
Inherited architect, decided by:
- Locality:
src/markdown/inline-content.ts:438applyClosing: every change a]makes to the scan happens here,linkOpenersFromone expression keyed onclosesLink - Locality:
src/markdown/inline-content.ts:425closeBracket: it only reads the scan and returns aClosinglisting the two outcomes - Locality:
src/markdown/inline-content.ts:179readToken: thebracket-closecase flushes like its neighbours
2026-11-09T04:00:13Z, PR #145 at 3c07509b73, against 1939359cb8
Ruling: better
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | better | better |
| Inherited architect | better | same | same | same | better |
Mid A, decided by:
- Self-sufficiency, Overall:
src/markdown/emit/unspellable-runs.test.ts:11lines: twelve worked lines give the exact runs a carry or a drop takes, where the base had no direct test ofunspellableRuns - Self-sufficiency:
src/markdown/emit/unspellable-runs.test.ts:87carryRuns: it shows the two call paths that reachunspellableRuns, which the base left to be traced acrossinline-line.tsandportable/inline-reduction.ts
Inherited architect, decided by:
- Navigation, Overall:
src/markdown/emit/unspellable-runs.test.ts:80lines: a sibling test besideunspellable-runs.tsholds twelve concrete lines under carry and drop, where the base had none
2026-11-09T04:44:01Z, PR #146 at 6f5087c, against 59453f6
Ruling: worse
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | worse | same | same | worse |
| Inherited architect | same | worse | same | same | worse |
Mid A, decided by:
- Locality, Overall:
src/markdown/portable/block-spelling.ts:45tryTaskList: the loop pushes into a placeholderitemarray that is dropped if the first child is not a task, so blocks vanish silently and whether that can happen is decided intask-list.tsitemParts; the base handled it locally - Locality:
src/markdown/portable/block-spelling.ts:46tryTaskList: anitemalias pushed intoitemsand changed throughitem.pushis more state across loop turns than the base'sitems.at(-1)
Inherited architect, decided by:
- Locality, Overall:
src/markdown/portable/block-spelling.ts:44tryTaskList: a stand-initemarray holds blocks pushed before the first task and loses them without a failure, so its safety rests onreduceTaskListandsplitTaskListin other files, where the base never lost a block - Locality:
src/markdown/portable/task-list.ts:42itemsOf: groups a task and its children up to the next task as the basetryTaskListdid, and the new loop breaks that match between the two places
2026-11-09T04:45:44Z, PR #146 at 6030d12, against 59453f6
Ruling: same
| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall |
|---|---|---|---|---|---|
| Mid A | same | same | same | same | same |
| Inherited architect | same | same | same | same | same |