@descent-vtt/spec-graph 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,18 @@ the family's
11
11
  [versioning policy](https://github.com/DescentVTT/spec-core/blob/main/docs/adr/0009-versions-before-1-0.md)
12
12
  records.
13
13
 
14
+ ## 0.11.1
15
+
16
+ Documentation and robustness: the README's SARIF example is pinned as CI
17
+ pins its own, and every scan steps past an empty match, so no table entry
18
+ can hang a run. Nothing a run answers has changed.
19
+
20
+ ### Documentation
21
+
22
+ - The README's SARIF example checks out and sets up Node itself, pins each
23
+ action to a commit with its version beside it, and keeps no token in the
24
+ checkout.
25
+
14
26
  ## 0.11.0
15
27
 
16
28
  spec-graph reads English only again, by the maintainer's decision; the
package/README.md CHANGED
@@ -1061,14 +1061,24 @@ permissions:
1061
1061
  contents: read
1062
1062
  security-events: write
1063
1063
  steps:
1064
- # check out the repository and set up Node, then:
1064
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
1065
+ with:
1066
+ persist-credentials: false
1067
+ - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
1068
+ with:
1069
+ node-version: '24'
1070
+ - run: npm ci
1065
1071
  - run: npx spec-graph --format sarif > spec-graph.sarif
1066
1072
  continue-on-error: true
1067
- - uses: github/codeql-action/upload-sarif@v4
1073
+ - uses: github/codeql-action/upload-sarif@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
1068
1074
  with:
1069
1075
  sarif_file: spec-graph.sarif
1070
1076
  ```
1071
1077
 
1078
+ The actions are pinned to commits, with the version beside each, because a tag
1079
+ can be moved and a commit cannot; Dependabot's `github-actions` updates keep
1080
+ pins like these current.
1081
+
1072
1082
  Findings land as comments on the changed lines, and they persist across commits
1073
1083
  without drifting, because the `partialFingerprints` spec-graph writes are the
1074
1084
  same identity a baseline is keyed on — the rule, the specification, and the
@@ -1277,9 +1287,9 @@ tools share, whose code is copied into `src/vendor/` and checked by hash rather
1277
1287
  than installed. So the whole package is auditable in an afternoon — and nothing
1278
1288
  in the pipeline can take longer than its input.
1279
1289
 
1280
- **Verified, not just covered.** 1,880 tests; 99.4% statement and 99.8% line
1290
+ **Verified, not just covered.** 1,886 tests; 99.4% statement and 99.8% line
1281
1291
  coverage. Coverage says a line ran, so the suite is also held to a mutation
1282
- score - 96.32% over 8,393 mutants, measured by CI's full sweep, and a build
1292
+ score - 96.31% over 8,385 mutants, measured by CI's full sweep, and a build
1283
1293
  fails under 93 - because a vocabulary entry or a boundary
1284
1294
  condition can be weakened by an ordinary-looking refactor without a single test
1285
1295
  going red. [ADR-0007](https://github.com/DescentVTT/spec-graph/blob/main/docs/adr/0007-mutation-testing.md) is straight about what
@@ -63,8 +63,7 @@ export function parseDirectives(comments) {
63
63
  const attributes = new Map();
64
64
  const unknown = [];
65
65
  const allowed = SCHEMA[directiveName];
66
- ATTRIBUTE.lastIndex = 0;
67
- for (let m = ATTRIBUTE.exec(body); m !== null; m = ATTRIBUTE.exec(body)) {
66
+ for (const m of body.matchAll(ATTRIBUTE)) {
68
67
  const key = m[1].toLowerCase();
69
68
  const quoted = m[3] ?? m[4];
70
69
  const bare = m[5];
@@ -1 +1 @@
1
- {"version":3,"file":"directives.js","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Explicit annotations, written as HTML comments.\n *\n * Inference covers the overwhelming majority of real documents, but inference\n * that cannot be overridden is a trap: the first time it guesses wrong about a\n * document somebody cannot restructure, the whole tool gets switched off. These\n * directives are the escape hatch, and they are HTML comments so they stay\n * invisible in GitHub, MkDocs, Docusaurus and every other renderer.\n *\n * ```md\n * <!-- @spec-node id=\"ADR-0007\" status=\"accepted\" aliases=\"adr-7, sharding\" -->\n * <!-- @spec-item id=\"shard-key\" state=\"narrowed\" -->\n * <!-- @spec-edge kind=\"delegates-to\" to=\"ADR-0011#scope\" -->\n * <!-- @spec-ignore -->\n * ```\n *\n * A directive always wins over anything inferred, and says so in the report, so\n * an override is visible rather than mysterious.\n */\n\nimport { isMarkdownLine, type HtmlComment, type ListItem, type ScannedDocument } from './markdown.js';\n\nexport type DirectiveName = 'spec-node' | 'spec-item' | 'spec-edge' | 'spec-ignore' | 'spec-history';\n\nconst KNOWN: ReadonlySet<string> = new Set<DirectiveName>([\n 'spec-node',\n 'spec-item',\n 'spec-edge',\n 'spec-ignore',\n 'spec-history',\n]);\n\nexport interface Attribute {\n readonly value: string;\n /** Absolute offset of the value text, quotes excluded. */\n readonly start: number;\n readonly end: number;\n}\n\nexport interface Directive {\n readonly name: DirectiveName;\n readonly attributes: ReadonlyMap<string, Attribute>;\n /** Offset of the enclosing comment. */\n readonly start: number;\n readonly end: number;\n readonly line: number;\n /** Attribute names that were written but are not part of this directive. */\n readonly unknownAttributes: readonly string[];\n}\n\nconst DIRECTIVE_HEAD = /^\\s*@([a-z][a-z0-9-]*)/;\nconst ATTRIBUTE = /([A-Za-z_][A-Za-z0-9_-]*)\\s*(?:=\\s*(\"([^\"]*)\"|'([^']*)'|([^\\s\"'<>]+)))?/g;\n\n/** Attributes each directive understands. Anything else is reported, not ignored. */\nconst SCHEMA: Readonly<Record<DirectiveName, readonly string[]>> = {\n 'spec-node': ['id', 'status', 'title', 'aliases', 'kind'],\n // Takes no attributes: the file either is a record or it is not. A mutant\n // that lists `Stryker was here` lists no name: one never holds a space.\n 'spec-history': [],\n 'spec-item': ['id', 'state', 'title', 'owner', 'note'],\n 'spec-edge': ['kind', 'to', 'from', 'reason'],\n 'spec-ignore': ['reason'],\n};\n\n/**\n * Reads every spec-graph directive out of a document's HTML comments.\n *\n * Only out of a comment that closes. One that opens a line and never does runs\n * to the end of the document, and read as a directive, a stray\n * `<!-- @spec-ignore` would drop the file, and a stray `<!-- @spec-node` would\n * take every `name=value` in the rest of it as an attribute.\n */\nexport function parseDirectives(comments: readonly HtmlComment[]): Directive[] {\n const out: Directive[] = [];\n for (const comment of comments) {\n if (comment.closed === false) continue;\n const head = DIRECTIVE_HEAD.exec(comment.inner);\n if (!head) continue;\n const name = head[1] as string;\n if (!KNOWN.has(name)) continue;\n\n const directiveName = name as DirectiveName;\n // The head is anchored, so it starts where the comment's text does.\n const bodyStart = (head[0] as string).length;\n const body = comment.inner.slice(bodyStart);\n const attributes = new Map<string, Attribute>();\n const unknown: string[] = [];\n const allowed = SCHEMA[directiveName];\n\n ATTRIBUTE.lastIndex = 0;\n for (let m = ATTRIBUTE.exec(body); m !== null; m = ATTRIBUTE.exec(body)) {\n const key = (m[1] as string).toLowerCase();\n const quoted = m[3] ?? m[4];\n const bare = m[5];\n // A bare attribute is a flag: `<!-- @spec-ignore reason -->`.\n const value = quoted ?? bare ?? 'true';\n const raw = m[2];\n const valueOffset =\n raw === undefined\n ? (m.index ?? 0) + (m[0] as string).length\n : (m.index ?? 0) + (m[0] as string).indexOf(raw) + (quoted === undefined ? 0 : 1);\n const start = comment.innerStart + bodyStart + valueOffset;\n\n if (!allowed.includes(key)) unknown.push(key);\n attributes.set(key, { value, start, end: start + value.length });\n }\n\n out.push({\n name: directiveName,\n attributes,\n start: comment.start,\n end: comment.end,\n line: comment.line,\n unknownAttributes: unknown,\n });\n }\n return out;\n}\n\n/** Reads an attribute, trimmed. Returns `null` when absent or blank. */\nexport function attr(directive: Directive, name: string): Attribute | null {\n const found = directive.attributes.get(name);\n if (!found) return null;\n const trimmed = found.value.trim();\n if (trimmed.length === 0) return null;\n const offset = found.value.indexOf(trimmed);\n return { value: trimmed, start: found.start + offset, end: found.start + offset + trimmed.length };\n}\n\n/** Splits a comma- or whitespace-separated attribute into its parts. */\nexport function attrList(directive: Directive, name: string): string[] {\n const found = attr(directive, name);\n if (!found) return [];\n // Whitespace is a separator, so no part holds any to trim. The filter drops\n // what a separator at either end leaves, and would drop what each separator\n // in a run leaves too, so splitting at one at a time is equivalent.\n return found.value.split(/[,;\\s]+/).filter((part) => part.length > 0);\n}\n\n/**\n * Finds the directive that annotates a given region.\n *\n * A `@spec-item` directive may sit on the line above the item, on the same\n * line, or inside the item body. All three read naturally in the source, so all\n * three are accepted, with the closest preceding directive winning.\n *\n * It answers for one region with no view of the others, so a directive in reach\n * of two items is found for both. Extraction uses `bindItemDirectives`.\n */\nexport function directiveFor(\n directives: readonly Directive[],\n name: DirectiveName,\n region: { start: number; end: number },\n /** How far above the region a directive may sit and still apply. */\n lookBehind: number,\n): Directive | null {\n let best: Directive | null = null;\n for (const directive of directives) {\n if (directive.name !== name) continue;\n const inside = directive.start >= region.start && directive.end <= region.end;\n const above = directive.end <= region.start && region.start - directive.end <= lookBehind;\n if (!inside && !above) continue;\n // Two directives never start at one offset, so `>=` reads the same.\n if (best === null || directive.start > best.start) best = directive;\n }\n return best;\n}\n\n/**\n * Pairs each `@spec-item` directive with the one list item it annotates.\n *\n * A directive is written for one item, so it binds to one: the item directly\n * below it, with nothing but blank lines and other comments between, or else\n * the item it is written in, the innermost where items nest. An item that\n * several bind to takes the last one written.\n *\n * A directive alone on its line is in an item only when indented further than\n * that item's marker, which is how CommonMark reads it. Indented under an item,\n * it annotates that item and not the sibling below; flush between two items, it\n * annotates the second.\n */\nexport function bindItemDirectives(\n scanned: ScannedDocument,\n directives: readonly Directive[],\n): Map<ListItem, Directive> {\n const bound = new Map<ListItem, Directive>();\n const wanted = directives.filter((directive) => directive.name === 'spec-item');\n // Most documents carry none. Sparing them the pass over their lines changes\n // how long this takes and nothing else.\n if (wanted.length === 0) return bound;\n\n const { lines, listItems } = scanned;\n const masked = scanned.masks.structure;\n // The indentation of each line holding nothing but whitespace and comments.\n // Code and raw-text HTML are masked too, so they are told apart by their flags.\n const quiet = new Map<number, number>();\n // For every other line, where the run of quiet lines directly above it began,\n // when there was one.\n const quietFrom = new Map<number, number | undefined>();\n let run: number | undefined;\n for (const line of lines) {\n if (isMarkdownLine(line) && masked.slice(line.contentStart, line.end).trim() === '') {\n quiet.set(line.line, line.indent);\n run ??= line.start;\n continue;\n }\n quietFrom.set(line.line, run);\n run = undefined;\n }\n\n // The items whose text the cursor is in, outermost first. Items nest, so one\n // that has ended is always on top. An item ends at the end of a line, the next\n // thing starts on a later one, and no two things start together, so `<` and\n // `<=` read alike in every comparison of offsets below.\n const open: ListItem[] = [];\n const close = (offset: number): void => {\n while (open.length > 0 && (open[open.length - 1] as ListItem).end <= offset) open.pop();\n };\n let next = 0;\n for (const directive of wanted) {\n while (next < listItems.length && (listItems[next] as ListItem).start < directive.start) {\n const item = listItems[next] as ListItem;\n close(item.start);\n open.push(item);\n next += 1;\n }\n close(directive.start);\n\n // Sharing its line with text, a directive is in whatever that text is in.\n const indent = quiet.get(directive.line) ?? Infinity;\n // No deeper than the scanner already went to find where these items end.\n let depth = open.length - 1;\n while (depth >= 0 && (open[depth] as ListItem).indent >= indent) depth -= 1;\n const holder = open[depth];\n\n const below = listItems[next];\n const directlyAbove = below !== undefined && (quietFrom.get(below.line) ?? Infinity) <= directive.start;\n if (directlyAbove && (holder === undefined || below.start < holder.end)) {\n bound.set(below, directive);\n continue;\n }\n // Flush under an item and above no other, it continues the item as any\n // unindented line does.\n const written = holder ?? open[open.length - 1];\n if (written !== undefined) bound.set(written, directive);\n }\n return bound;\n}\n"]}
1
+ {"version":3,"file":"directives.js","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Explicit annotations, written as HTML comments.\n *\n * Inference covers the overwhelming majority of real documents, but inference\n * that cannot be overridden is a trap: the first time it guesses wrong about a\n * document somebody cannot restructure, the whole tool gets switched off. These\n * directives are the escape hatch, and they are HTML comments so they stay\n * invisible in GitHub, MkDocs, Docusaurus and every other renderer.\n *\n * ```md\n * <!-- @spec-node id=\"ADR-0007\" status=\"accepted\" aliases=\"adr-7, sharding\" -->\n * <!-- @spec-item id=\"shard-key\" state=\"narrowed\" -->\n * <!-- @spec-edge kind=\"delegates-to\" to=\"ADR-0011#scope\" -->\n * <!-- @spec-ignore -->\n * ```\n *\n * A directive always wins over anything inferred, and says so in the report, so\n * an override is visible rather than mysterious.\n */\n\nimport { isMarkdownLine, type HtmlComment, type ListItem, type ScannedDocument } from './markdown.js';\n\nexport type DirectiveName = 'spec-node' | 'spec-item' | 'spec-edge' | 'spec-ignore' | 'spec-history';\n\nconst KNOWN: ReadonlySet<string> = new Set<DirectiveName>([\n 'spec-node',\n 'spec-item',\n 'spec-edge',\n 'spec-ignore',\n 'spec-history',\n]);\n\nexport interface Attribute {\n readonly value: string;\n /** Absolute offset of the value text, quotes excluded. */\n readonly start: number;\n readonly end: number;\n}\n\nexport interface Directive {\n readonly name: DirectiveName;\n readonly attributes: ReadonlyMap<string, Attribute>;\n /** Offset of the enclosing comment. */\n readonly start: number;\n readonly end: number;\n readonly line: number;\n /** Attribute names that were written but are not part of this directive. */\n readonly unknownAttributes: readonly string[];\n}\n\nconst DIRECTIVE_HEAD = /^\\s*@([a-z][a-z0-9-]*)/;\nconst ATTRIBUTE = /([A-Za-z_][A-Za-z0-9_-]*)\\s*(?:=\\s*(\"([^\"]*)\"|'([^']*)'|([^\\s\"'<>]+)))?/g;\n\n/** Attributes each directive understands. Anything else is reported, not ignored. */\nconst SCHEMA: Readonly<Record<DirectiveName, readonly string[]>> = {\n 'spec-node': ['id', 'status', 'title', 'aliases', 'kind'],\n // Takes no attributes: the file either is a record or it is not. A mutant\n // that lists `Stryker was here` lists no name: one never holds a space.\n 'spec-history': [],\n 'spec-item': ['id', 'state', 'title', 'owner', 'note'],\n 'spec-edge': ['kind', 'to', 'from', 'reason'],\n 'spec-ignore': ['reason'],\n};\n\n/**\n * Reads every spec-graph directive out of a document's HTML comments.\n *\n * Only out of a comment that closes. One that opens a line and never does runs\n * to the end of the document, and read as a directive, a stray\n * `<!-- @spec-ignore` would drop the file, and a stray `<!-- @spec-node` would\n * take every `name=value` in the rest of it as an attribute.\n */\nexport function parseDirectives(comments: readonly HtmlComment[]): Directive[] {\n const out: Directive[] = [];\n for (const comment of comments) {\n if (comment.closed === false) continue;\n const head = DIRECTIVE_HEAD.exec(comment.inner);\n if (!head) continue;\n const name = head[1] as string;\n if (!KNOWN.has(name)) continue;\n\n const directiveName = name as DirectiveName;\n // The head is anchored, so it starts where the comment's text does.\n const bodyStart = (head[0] as string).length;\n const body = comment.inner.slice(bodyStart);\n const attributes = new Map<string, Attribute>();\n const unknown: string[] = [];\n const allowed = SCHEMA[directiveName];\n\n for (const m of body.matchAll(ATTRIBUTE)) {\n const key = (m[1] as string).toLowerCase();\n const quoted = m[3] ?? m[4];\n const bare = m[5];\n // A bare attribute is a flag: `<!-- @spec-ignore reason -->`.\n const value = quoted ?? bare ?? 'true';\n const raw = m[2];\n const valueOffset =\n raw === undefined\n ? (m.index ?? 0) + (m[0] as string).length\n : (m.index ?? 0) + (m[0] as string).indexOf(raw) + (quoted === undefined ? 0 : 1);\n const start = comment.innerStart + bodyStart + valueOffset;\n\n if (!allowed.includes(key)) unknown.push(key);\n attributes.set(key, { value, start, end: start + value.length });\n }\n\n out.push({\n name: directiveName,\n attributes,\n start: comment.start,\n end: comment.end,\n line: comment.line,\n unknownAttributes: unknown,\n });\n }\n return out;\n}\n\n/** Reads an attribute, trimmed. Returns `null` when absent or blank. */\nexport function attr(directive: Directive, name: string): Attribute | null {\n const found = directive.attributes.get(name);\n if (!found) return null;\n const trimmed = found.value.trim();\n if (trimmed.length === 0) return null;\n const offset = found.value.indexOf(trimmed);\n return { value: trimmed, start: found.start + offset, end: found.start + offset + trimmed.length };\n}\n\n/** Splits a comma- or whitespace-separated attribute into its parts. */\nexport function attrList(directive: Directive, name: string): string[] {\n const found = attr(directive, name);\n if (!found) return [];\n // Whitespace is a separator, so no part holds any to trim. The filter drops\n // what a separator at either end leaves, and would drop what each separator\n // in a run leaves too, so splitting at one at a time is equivalent.\n return found.value.split(/[,;\\s]+/).filter((part) => part.length > 0);\n}\n\n/**\n * Finds the directive that annotates a given region.\n *\n * A `@spec-item` directive may sit on the line above the item, on the same\n * line, or inside the item body. All three read naturally in the source, so all\n * three are accepted, with the closest preceding directive winning.\n *\n * It answers for one region with no view of the others, so a directive in reach\n * of two items is found for both. Extraction uses `bindItemDirectives`.\n */\nexport function directiveFor(\n directives: readonly Directive[],\n name: DirectiveName,\n region: { start: number; end: number },\n /** How far above the region a directive may sit and still apply. */\n lookBehind: number,\n): Directive | null {\n let best: Directive | null = null;\n for (const directive of directives) {\n if (directive.name !== name) continue;\n const inside = directive.start >= region.start && directive.end <= region.end;\n const above = directive.end <= region.start && region.start - directive.end <= lookBehind;\n if (!inside && !above) continue;\n // Two directives never start at one offset, so `>=` reads the same.\n if (best === null || directive.start > best.start) best = directive;\n }\n return best;\n}\n\n/**\n * Pairs each `@spec-item` directive with the one list item it annotates.\n *\n * A directive is written for one item, so it binds to one: the item directly\n * below it, with nothing but blank lines and other comments between, or else\n * the item it is written in, the innermost where items nest. An item that\n * several bind to takes the last one written.\n *\n * A directive alone on its line is in an item only when indented further than\n * that item's marker, which is how CommonMark reads it. Indented under an item,\n * it annotates that item and not the sibling below; flush between two items, it\n * annotates the second.\n */\nexport function bindItemDirectives(\n scanned: ScannedDocument,\n directives: readonly Directive[],\n): Map<ListItem, Directive> {\n const bound = new Map<ListItem, Directive>();\n const wanted = directives.filter((directive) => directive.name === 'spec-item');\n // Most documents carry none. Sparing them the pass over their lines changes\n // how long this takes and nothing else.\n if (wanted.length === 0) return bound;\n\n const { lines, listItems } = scanned;\n const masked = scanned.masks.structure;\n // The indentation of each line holding nothing but whitespace and comments.\n // Code and raw-text HTML are masked too, so they are told apart by their flags.\n const quiet = new Map<number, number>();\n // For every other line, where the run of quiet lines directly above it began,\n // when there was one.\n const quietFrom = new Map<number, number | undefined>();\n let run: number | undefined;\n for (const line of lines) {\n if (isMarkdownLine(line) && masked.slice(line.contentStart, line.end).trim() === '') {\n quiet.set(line.line, line.indent);\n run ??= line.start;\n continue;\n }\n quietFrom.set(line.line, run);\n run = undefined;\n }\n\n // The items whose text the cursor is in, outermost first. Items nest, so one\n // that has ended is always on top. An item ends at the end of a line, the next\n // thing starts on a later one, and no two things start together, so `<` and\n // `<=` read alike in every comparison of offsets below.\n const open: ListItem[] = [];\n const close = (offset: number): void => {\n while (open.length > 0 && (open[open.length - 1] as ListItem).end <= offset) open.pop();\n };\n let next = 0;\n for (const directive of wanted) {\n while (next < listItems.length && (listItems[next] as ListItem).start < directive.start) {\n const item = listItems[next] as ListItem;\n close(item.start);\n open.push(item);\n next += 1;\n }\n close(directive.start);\n\n // Sharing its line with text, a directive is in whatever that text is in.\n const indent = quiet.get(directive.line) ?? Infinity;\n // No deeper than the scanner already went to find where these items end.\n let depth = open.length - 1;\n while (depth >= 0 && (open[depth] as ListItem).indent >= indent) depth -= 1;\n const holder = open[depth];\n\n const below = listItems[next];\n const directlyAbove = below !== undefined && (quietFrom.get(below.line) ?? Infinity) <= directive.start;\n if (directlyAbove && (holder === undefined || below.start < holder.end)) {\n bound.set(below, directive);\n continue;\n }\n // Flush under an item and above no other, it continues the item as any\n // unindented line does.\n const written = holder ?? open[open.length - 1];\n if (written !== undefined) bound.set(written, directive);\n }\n return bound;\n}\n"]}
package/dist/extract.js CHANGED
@@ -1208,12 +1208,15 @@ function ownerOf(items, offset) {
1208
1208
  export function classifyReference(text, start, end, section) {
1209
1209
  const before = sentenceBefore(text, start);
1210
1210
  // Left to right, so the last match within the window is the nearest one - and
1211
- // the nearest governing phrase is the one that governs.
1211
+ // the nearest governing phrase is the one that governs. `matchAll`, not a
1212
+ // loop over `exec`: an empty match leaves `lastIndex` where it began, and
1213
+ // `exec` finds it there again for ever, where `matchAll` steps past it. No
1214
+ // phrase is empty, so the pattern never matches empty; a phrase emptied by
1215
+ // mistake then fails the tests rather than hanging them.
1212
1216
  let best = null;
1213
- VERB_PATTERN.lastIndex = 0;
1214
- for (let m = VERB_PATTERN.exec(before); m !== null; m = VERB_PATTERN.exec(before)) {
1217
+ for (const m of before.matchAll(VERB_PATTERN)) {
1215
1218
  const phrase = m[0];
1216
- const end = (m.index ?? 0) + phrase.length;
1219
+ const end = m.index + phrase.length;
1217
1220
  const distance = before.length - end;
1218
1221
  if (distance > VERB_WINDOW)
1219
1222
  continue;
@@ -1279,10 +1282,8 @@ const STATEMENT_BREAK = /[.?!;]\s|[。?!;]|\n\s*\n|\n\s*[-*+>#]|\|/g;
1279
1282
  function sentenceBefore(text, start) {
1280
1283
  const window = text.slice(Math.max(0, start - 160), start);
1281
1284
  let cut = 0;
1282
- STATEMENT_BREAK.lastIndex = 0;
1283
- for (let m = STATEMENT_BREAK.exec(window); m !== null; m = STATEMENT_BREAK.exec(window)) {
1284
- cut = (m.index ?? 0) + m[0].length;
1285
- }
1285
+ for (const m of window.matchAll(STATEMENT_BREAK))
1286
+ cut = m.index + m[0].length;
1286
1287
  return window
1287
1288
  .slice(cut)
1288
1289
  .toLowerCase()
@@ -1333,8 +1334,7 @@ function findBareReferences(scanned, links) {
1333
1334
  }
1334
1335
  text += source.slice(cursor);
1335
1336
  const out = [];
1336
- BARE_REF.lastIndex = 0;
1337
- for (let m = BARE_REF.exec(text); m !== null; m = BARE_REF.exec(text)) {
1337
+ for (const m of text.matchAll(BARE_REF)) {
1338
1338
  const written = m[0];
1339
1339
  // The family as resolution will read it, which takes the shortest prefix
1340
1340
  // the number allows: `base64` is `base` and 64. Read off this pattern's
@@ -1 +1 @@
1
- {"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Document extraction: Markdown in, graph fragments out.\n *\n * This module is where domain-agnosticism is won or lost. It never requires a\n * repository to adopt a syntax. It reads what teams already write - front\n * matter, a `## Status` section, a checklist under `## Open Questions`, a link\n * that says \"deferred to ADR-0011\" - and turns each into a typed relation with a\n * source position.\n *\n * The one rule it holds to everywhere: **an inference that cannot be justified\n * is not made.** An unrecognised status becomes `unknown`, not a guess. A link\n * with no governing verb becomes a neutral `references`, not a dependency. Bare\n * identifiers found in prose are opportunistic and are dropped silently when\n * they do not resolve, because the alternative is reporting `SHA-256` as a\n * broken reference to specification 256.\n */\n\nimport { attr, attrList, bindItemDirectives, parseDirectives, type Directive } from './directives.js';\nimport {\n identify,\n isDocumentTarget,\n isExternal,\n looksLikePath,\n normaliseRef,\n parsePrefixedRef,\n withinOneEdit,\n type DocumentIdentity,\n ID_KEYS,\n} from './identity.js';\nimport { isStatusHeading, phaseFromPath, phaseOf, STATUS_KEYS, supersessionTargetsIn } from './lifecycle.js';\nimport {\n anchorsOf,\n isMarkdownLine,\n isOnlyComment,\n referenceLinks,\n scanMarkdown,\n slugify,\n type Link,\n type ListItem,\n type ScannedDocument,\n type TableCell,\n} from './markdown.js';\nimport {\n findSpecificationRegions,\n isRegisterTable,\n opensHeading,\n regionAt,\n type SpecificationRegion,\n} from './sections.js';\nimport { resolveItemState } from './state.js';\nimport { refOf, type LineIndex } from './source.js';\nimport type {\n DocumentNode,\n EdgeKind,\n EdgeOrigin,\n ItemNode,\n MisreadKey,\n ParseProblem,\n Phase,\n SourceRef,\n} from './types.js';\nimport { readEntries, toRecord, valuesOf, type YamlEntry } from './yaml.js';\n\n/* -------------------------------------------------------------------------- */\n/* Output */\n/* -------------------------------------------------------------------------- */\n\n/**\n * A relation that has been read but not yet resolved to a target node.\n *\n * Resolution needs the whole corpus, so extraction stops at the raw target text.\n */\nexport interface ReferenceCandidate {\n readonly kind: EdgeKind;\n /** Id of the node the relation was written on. */\n readonly from: string;\n /** The target exactly as written: a path, an identifier, or a URL. */\n readonly target: string;\n readonly origin: EdgeOrigin;\n readonly declaredAt: SourceRef;\n readonly raw: string;\n /**\n * When true the relation runs `target -> from`.\n *\n * `superseded-by: ADR-0009` written in ADR-0003 declares that *ADR-0009*\n * supersedes ADR-0003. The edge belongs to ADR-0009; the line a human must go\n * and fix is in ADR-0003, which is why `declaredAt` is tracked separately.\n */\n readonly inverted: boolean;\n /**\n * Opportunistic references are dropped in silence when they do not resolve.\n * Only deliberate ones - links, front matter, directives - are reported.\n */\n readonly opportunistic: boolean;\n}\n\nexport interface ExtractedDocument {\n readonly document: DocumentNode;\n readonly items: readonly ItemNode[];\n readonly references: readonly ReferenceCandidate[];\n readonly problems: readonly ParseProblem[];\n /**\n * Front-matter keys that read as relations and declared none.\n *\n * Kept apart from `problems` because a problem is about the text and this is\n * about the graph: the edge the author wrote down is not in it.\n */\n readonly misreadKeys: readonly MisreadKey[];\n /** Heading slugs and GitHub's anchors, for resolving `#anchor` references into this document. */\n readonly anchors: ReadonlySet<string>;\n readonly identity: DocumentIdentity;\n readonly scanned: ScannedDocument;\n /**\n * Specifications declared inside this file, each a document in its own right.\n *\n * Empty for the ordinary one-file-per-decision layout, which is why nothing\n * downstream had to change to support registers.\n */\n readonly subSpecifications: readonly ExtractedDocument[];\n /**\n * The file-level specification this one is a region of, if any.\n *\n * Recorded so the register's structure is a relation in the graph rather than\n * an accident of which offsets fall inside which: \"what decisions does this\n * register hold\" is a question worth being able to ask.\n */\n readonly containerId: string | null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Vocabulary */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Front-matter keys that declare a relation, and what they mean.\n *\n * Every directional kind is spelled in **both** directions. A register that\n * records `depends-on` but not `depended-on-by` is not a smaller vocabulary, it\n * is a trap: the author writes the inverse, the key means nothing, and the edge\n * they declared is missing from a graph that reports itself as consistent. Which\n * half of a pair a repository writes is a filing convention, and a filing\n * convention is not something a linter gets to have an opinion about.\n *\n * `relates-to` is the exception, and it is not one: the relation is symmetric,\n * so it has no other direction to spell. `contains` is structural and never\n * written by hand. `tests/parsing.test.ts` holds both facts to the fire.\n */\nexport const RELATION_KEYS: Readonly<Record<string, { kind: EdgeKind; inverted: boolean }>> = {\n supersedes: { kind: 'supersedes', inverted: false },\n supercedes: { kind: 'supersedes', inverted: false },\n replaces: { kind: 'supersedes', inverted: false },\n obsoletes: { kind: 'supersedes', inverted: false },\n deprecates: { kind: 'supersedes', inverted: false },\n 'superseded-by': { kind: 'supersedes', inverted: true },\n 'superceded-by': { kind: 'supersedes', inverted: true },\n 'replaced-by': { kind: 'supersedes', inverted: true },\n 'obsoleted-by': { kind: 'supersedes', inverted: true },\n 'deprecated-by': { kind: 'supersedes', inverted: true },\n 'rolled-into': { kind: 'supersedes', inverted: true },\n amends: { kind: 'amends', inverted: false },\n extends: { kind: 'amends', inverted: false },\n refines: { kind: 'amends', inverted: false },\n clarifies: { kind: 'amends', inverted: false },\n revises: { kind: 'amends', inverted: false },\n 'amended-by': { kind: 'amends', inverted: true },\n 'extended-by': { kind: 'amends', inverted: true },\n 'refined-by': { kind: 'amends', inverted: true },\n 'clarified-by': { kind: 'amends', inverted: true },\n 'revised-by': { kind: 'amends', inverted: true },\n 'depends-on': { kind: 'depends-on', inverted: false },\n 'dependent-on': { kind: 'depends-on', inverted: false },\n dependencies: { kind: 'depends-on', inverted: false },\n requires: { kind: 'depends-on', inverted: false },\n 'builds-on': { kind: 'depends-on', inverted: false },\n 'relies-on': { kind: 'depends-on', inverted: false },\n 'depended-on-by': { kind: 'depends-on', inverted: true },\n 'required-by': { kind: 'depends-on', inverted: true },\n dependents: { kind: 'depends-on', inverted: true },\n assumes: { kind: 'assumes', inverted: false },\n 'assumed-by': { kind: 'assumes', inverted: true },\n 'blocked-by': { kind: 'blocked-by', inverted: false },\n 'blocked-on': { kind: 'blocked-by', inverted: false },\n 'waiting-on': { kind: 'blocked-by', inverted: false },\n 'waiting-for': { kind: 'blocked-by', inverted: false },\n 'gated-on': { kind: 'blocked-by', inverted: false },\n 'gated-by': { kind: 'blocked-by', inverted: false },\n blocks: { kind: 'blocked-by', inverted: true },\n 'delegates-to': { kind: 'delegates-to', inverted: false },\n 'delegated-to': { kind: 'delegates-to', inverted: false },\n 'deferred-to': { kind: 'delegates-to', inverted: false },\n 'tracked-in': { kind: 'delegates-to', inverted: false },\n 'tracked-by': { kind: 'delegates-to', inverted: false },\n 'continued-in': { kind: 'delegates-to', inverted: false },\n 'delegated-from': { kind: 'delegates-to', inverted: true },\n related: { kind: 'relates-to', inverted: false },\n 'relates-to': { kind: 'relates-to', inverted: false },\n 'related-to': { kind: 'relates-to', inverted: false },\n 'see-also': { kind: 'relates-to', inverted: false },\n references: { kind: 'references', inverted: false },\n reference: { kind: 'references', inverted: false },\n refs: { kind: 'references', inverted: false },\n 'referenced-by': { kind: 'references', inverted: true },\n};\n\n/**\n * True when a front-matter value is shaped like a citation.\n *\n * The second half of the gate on {@link misreadRelationKeys}, and the half that\n * does the work. `sidebar_position: 4` and `ref: main` are a hair away from a\n * relation key by spelling alone; neither carries anything that could name a\n * document, and reporting them would make the rule an irritation rather than a\n * catch (ADR-0006).\n */\nfunction looksLikeCitation(value: string): boolean {\n // A blank value needs no case of its own: it is neither an identifier nor a\n // path, so both tests below already answer no.\n const trimmed = value.trim();\n if (parsePrefixedRef(trimmed) !== null) return true;\n return looksLikePath(trimmed) && isDocumentTarget(trimmed) && !isExternal(trimmed);\n}\n\n/**\n * Front-matter keys that read as relations and declare none.\n *\n * Front matter is an open vocabulary and most of what lives there is nobody\n * else's business, so the bar is deliberately high: the key has to be one edit\n * from a relation key *and* carry something that could name a document. Both\n * conditions together are what separates `dependson: ADR-0001`, which is an edge\n * the author believes exists, from `description: ...`, which is a title.\n */\nfunction misreadRelationKeys(\n byKey: ReadonlyMap<string, YamlEntry>,\n from: string,\n at: (start: number, end: number) => SourceRef,\n): MisreadKey[] {\n const out: MisreadKey[] = [];\n for (const [key, entry] of byKey) {\n const folded = foldRelationKey(key);\n // A key of nothing but punctuation folds to nothing. The shortest relation\n // key folds to four letters, so the edit test below would pass it over too\n // and no test can see this half; it keeps that true for any future key.\n if (folded.length === 0 || RELATION_INDEX.has(folded)) continue;\n if (!valuesOf(entry).some(looksLikeCitation)) continue;\n const near = [...RELATION_INDEX.values()]\n .filter((relation) => withinOneEdit(folded, foldRelationKey(relation.canonical)))\n .map((relation) => relation.canonical);\n if (near.length === 0) continue;\n out.push({ key, suggestion: near.join(', '), from, at: at(entry.start, entry.end) });\n }\n return out;\n}\n\n/**\n * Folds a front-matter key to its lookup form.\n *\n * `depends-on`, `depends_on`, `dependsOn` and `Depends On` are one key written\n * four ways, and which one a repository uses is decided by whatever wrote the\n * front matter first. Dropping every separator collapses them - the YAML reader\n * has already lower-cased the key, which is what makes camel case fold too.\n *\n * Which case this folds to is arbitrary and no test pins it: both sides of every\n * comparison come through here, so upper would work exactly as well. Asserting\n * on it would be asserting on the implementation.\n */\nexport function foldRelationKey(key: string): string {\n return key.replace(/[^a-z0-9]/gi, '').toLowerCase();\n}\n\n/** The vocabulary above, indexed by folded key. */\nconst RELATION_INDEX: ReadonlyMap<string, { kind: EdgeKind; inverted: boolean; canonical: string }> = new Map(\n Object.entries(RELATION_KEYS).map(([canonical, relation]) => [\n foldRelationKey(canonical),\n { ...relation, canonical },\n ]),\n);\n\n/**\n * Whether a front-matter key is one the graph is built from: a status, an id\n * or an alias, or a relation. Left unread, each changes a verdict - a status\n * is unknown, a node is named by its path, an edge is missing. A title or a\n * description left unread changes a label.\n */\nfunction buildsGraph(key: string): boolean {\n return (\n STATUS_KEYS.includes(key) ||\n ID_KEYS.includes(key) ||\n key === 'alias' ||\n key === 'aliases' ||\n RELATION_INDEX.has(foldRelationKey(key))\n );\n}\n\n/**\n * Keys a region must answer for itself, so the file's answer cannot shadow one.\n *\n * Identity and status and title are the three things a register exists to vary\n * row by row. The rest of the file's front matter describes the file, and a\n * decision inside the file is described by it too.\n */\nconst UNINHERITED: ReadonlySet<string> = new Set([...ID_KEYS, ...STATUS_KEYS, 'title', 'alias', 'aliases']);\n\n/**\n * The front matter a region inherits from the file that contains it.\n *\n * [ADR-0009](../docs/adr/0009-a-specification-is-a-region.md) left this open,\n * and [ADR-0016](../docs/adr/0016-a-query-needs-a-sentence.md) made leaving it\n * open a defect. A repository can now write `document[fm.owner!=platform]` as a\n * rule of its own, and on a register every region answered nothing - which\n * `!=` reads as a mismatch, because an absent value is not the value. A file\n * whose front matter said `owner: platform` was reported twice for not being\n * owned by platform, and the message rendered `{0.fm.owner}` as the literal\n * placeholder. Confident, wrong, and unanswerable: the ADR-0006 failure.\n *\n * Two kinds of key stay behind. A relation key is a claim the file made -\n * `supersedes:` at the top of a register supersedes on behalf of the register,\n * not on behalf of each decision in it, and the edges were built from the\n * file's entries before this ran. And a key the region answers itself must not\n * be shadowed, which is {@link UNINHERITED}.\n */\nexport function inheritableFrontMatter(\n entries: readonly YamlEntry[],\n): Readonly<Record<string, string | readonly string[]>> {\n return toRecord(\n entries.filter((entry) => !UNINHERITED.has(entry.key) && !RELATION_INDEX.has(foldRelationKey(entry.key))),\n );\n}\n\n/**\n * Phrases that give a link its meaning, longest-matching-nearest wins.\n *\n * Only phrases that genuinely commit the citing document are here. Vague ones\n * (\"see\", \"covered by\") stay out: a `references` edge is harmless, whereas a\n * wrongly inferred `assumes` edge produces a confident stale-premise finding\n * about a document that never depended on anything.\n */\nconst VERB_RULES: readonly { kind: EdgeKind; inverted: boolean; phrases: readonly string[] }[] = [\n {\n kind: 'supersedes',\n inverted: true,\n phrases: ['superseded by', 'superceded by', 'replaced by', 'obsoleted by', 'deprecated by', 'rolled into'],\n },\n { kind: 'supersedes', inverted: false, phrases: ['supersedes', 'supercedes', 'replaces', 'obsoletes', 'deprecates'] },\n { kind: 'amends', inverted: true, phrases: ['amended by', 'refined by', 'clarified by', 'revised by'] },\n { kind: 'amends', inverted: false, phrases: ['amends', 'refines', 'clarifies', 'revises'] },\n {\n kind: 'delegates-to',\n inverted: false,\n phrases: [\n 'delegated to',\n 'delegate to',\n 'deferred to',\n 'defer to',\n 'moved to',\n 'move to',\n 'tracked in',\n 'tracked by',\n 'handed off to',\n 'handed to',\n 'hand off to',\n 'follow up in',\n 'follow-up in',\n 'followup in',\n 'continued in',\n 'continues in',\n 'punted to',\n 'left to',\n 'belongs in',\n 'owned by',\n 'will be decided in',\n 'will be resolved in',\n 'will be handled in',\n 'will be handled by',\n 'will be answered in',\n 'to be decided in',\n 'to be resolved in',\n 'to be handled in',\n 'to be answered in',\n ],\n },\n {\n kind: 'blocked-by',\n inverted: false,\n phrases: ['blocked by', 'blocked on', 'waiting on', 'waiting for', 'gated on', 'gated by', 'unblocked by'],\n },\n { kind: 'blocked-by', inverted: true, phrases: ['blocks', 'blocking'] },\n {\n kind: 'depends-on',\n inverted: false,\n phrases: ['depends on', 'depend on', 'dependent on', 'requires', 'builds on', 'built on', 'relies on'],\n },\n { kind: 'depends-on', inverted: true, phrases: ['depended on by'] },\n {\n kind: 'assumes',\n inverted: false,\n phrases: [\n 'assumes',\n 'assuming',\n 'on the assumption of',\n 'as decided in',\n 'as established in',\n 'as established by',\n 'as stated in',\n 'as specified in',\n 'as required by',\n 'as mandated by',\n 'in accordance with',\n 'constrained by',\n 'mandated by',\n 'governed by',\n 'predicated on',\n 'rests on',\n 'follows from',\n 'justified by',\n // A constraint the citing document designs around. \"the row limit imposed\n // by ADR-0002\" is the archetypal stale premise: when ADR-0002 is retired,\n // this document is still working around a cap that no longer exists.\n 'imposed by',\n 'required by',\n 'dictated by',\n 'determined by',\n 'limited by',\n 'capped by',\n 'bounded by',\n 'defined by',\n 'defined in',\n 'specified by',\n 'set by',\n 'per',\n 'because',\n 'since',\n ],\n },\n];\n\n/**\n * Words that cancel a governing phrase standing before them.\n *\n * The window allows a short noun phrase between a verb and the reference it\n * governs - \"deferred to the sharding decision in [ADR-7]\" is one statement.\n * It cannot allow a negation. A table entry reading \"Owned by nobody today and\n * disclaimed by [138]\" was being read as a delegation *to* 138, which is the\n * opposite of what the sentence says, and an inference that inverts its source\n * is worse than no inference at all.\n *\n * The `^` never decides anything: the text tested starts just after a phrase,\n * and a phrase only matches where no letter follows it.\n */\nconst NEGATION = /(?:^|\\s)(?:no|not|nobody|none|never|neither|nor|nothing|without)(?:\\s|$)/;\n\n/** How close a governing phrase must sit to the reference it governs. */\nconst VERB_WINDOW = 40;\n\n/**\n * Every governing phrase compiled into one alternation, plus a lookup table.\n *\n * Classification runs on every reference in the corpus, and testing a hundred\n * phrases one at a time made it the most expensive thing extraction did. The\n * alternation is sorted longest-first so that at any given position the regex\n * prefers `partially resolved` over `resolved`, matching the precedence the\n * per-phrase search had. Lookarounds rather than `\\b`, because phrases contain\n * hyphens and `\\b` does the wrong thing around them.\n *\n * Neither the sort nor the escaping decides anything today, and no test can\n * pin them: no phrase in the table is another one followed by more words, and\n * none holds a character a pattern would read. Both are for the next phrase.\n */\nconst VERB_LOOKUP: ReadonlyMap<string, Classification> = new Map(\n VERB_RULES.flatMap((rule) =>\n rule.phrases.map((phrase) => [phrase, { kind: rule.kind, inverted: rule.inverted }] as const),\n ),\n);\n\nconst VERB_PATTERN = new RegExp(\n `(?<![\\\\p{L}\\\\p{N}])(?:${[...VERB_LOOKUP.keys()]\n .sort((a, b) => b.length - a.length)\n .map((phrase) => phrase.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n .join('|')})(?![\\\\p{L}\\\\p{N}])`,\n 'gu',\n);\n\n/** Headings under which a link is bookkeeping rather than a commitment. */\nconst WEAK_SECTIONS: ReadonlySet<string> = new Set([\n 'see also',\n 'references',\n 'reference',\n 'related',\n 'related work',\n 'related decisions',\n 'related documents',\n 'links',\n 'further reading',\n 'prior art',\n 'history',\n 'changelog',\n 'change log',\n 'revision history',\n 'bibliography',\n 'sources',\n 'appendix',\n 'more information',\n 'resources',\n 'index',\n]);\n\n/** Headings whose bullets are obligations even without a checkbox. */\nconst OBLIGATION_SECTIONS: ReadonlySet<string> = new Set([\n 'open questions',\n 'open question',\n 'unresolved questions',\n 'unanswered questions',\n 'questions',\n 'open issues',\n 'action items',\n 'actions',\n 'todo',\n 'to do',\n 'to-do',\n 'todos',\n 'next steps',\n 'follow ups',\n 'follow-ups',\n 'followups',\n 'follow up',\n 'follow-up',\n 'unresolved',\n 'outstanding',\n 'outstanding questions',\n 'tasks',\n 'task list',\n 'work items',\n 'remaining work',\n 'decisions needed',\n 'blockers',\n 'parking lot',\n 'future work',\n 'deferred',\n]);\n\n/**\n * Prefixes that look like specification identifiers but never are.\n *\n * The corpus filter in `resolve.ts` is the real defence; this list only keeps\n * the obvious noise out of the candidate set. A single letter - `v2`, `x86`,\n * `p99` - is not here because no prefix that short is ever read as a family.\n */\nconst NOT_A_FAMILY: ReadonlySet<string> = new Set([\n 'ver',\n 'version',\n 'pp',\n 'fig',\n 'figure',\n 'table',\n 'tbl',\n 'section',\n 'sect',\n 'sec',\n 'step',\n 'item',\n 'no',\n 'num',\n 'line',\n 'ln',\n 'col',\n 'port',\n 'pr',\n 'issue',\n 'gh',\n 'utf',\n 'ascii',\n 'sha',\n 'md',\n 'http',\n 'https',\n 'ipv',\n 'tls',\n 'ssl',\n 'es',\n 'ecma',\n 'p99',\n 'base',\n 'sql',\n 'ipv4',\n 'ipv6',\n 'arm',\n 'x86',\n 'win',\n 'node',\n 'python',\n 'java',\n 'go',\n 'cpp',\n]);\n\nconst BARE_REF = /\\b[A-Za-z][A-Za-z0-9]{0,14}[\\s._-]?\\d{1,6}\\b/g;\n\n/* -------------------------------------------------------------------------- */\n/* Extraction */\n/* -------------------------------------------------------------------------- */\n\nexport interface ExtractInput {\n /** Repository-relative POSIX path. */\n readonly path: string;\n readonly text: string;\n /**\n * This file is a historical record: a log of what was decided, not a\n * decision. Matched against the caller's history patterns, because deciding\n * which files those are is a repository's business and not a guess this\n * layer could justify making. See ADR-0011.\n */\n readonly record?: boolean | undefined;\n}\n\n/**\n * Reads one file into graph fragments, one entry per specification in it.\n *\n * A file yields at least itself. It yields more when it is a register: a\n * heading that carries an identifier *and* declares a status is a specification\n * in its own right, with its own lifecycle, its own obligations and its own\n * relations. See ADR-0009.\n */\nexport function extractSpecifications(input: ExtractInput): ExtractedDocument[] {\n const first = extractDocument(input);\n return first === null ? [] : [first, ...(first.subSpecifications as ExtractedDocument[])];\n}\n\n/** Reads a file's own specification. Returns `null` when it opts out. */\n/** The one character that makes a text file read as binary to other tools. */\nconst NUL = '\\u0000';\n\nexport function extractDocument(input: ExtractInput): ExtractedDocument | null {\n const scanned = scanMarkdown(input.text);\n const directives = parseDirectives(scanned.comments);\n if (directives.some((d) => d.name === 'spec-ignore')) return null;\n\n const index = scanned.index;\n const file = input.path;\n const problems: ParseProblem[] = [];\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n const nul = input.text.indexOf(NUL);\n if (nul !== -1) {\n // Not a finding. Nothing about the graph is wrong, and the text parsed - a\n // NUL is whitespace to every rule here. It is a problem with the *input*,\n // which is what a ParseProblem is for, and it is worth one line because\n // spec-graph is likely the only tool that got this far: grep, diff and\n // every review interface read the file as binary and show nothing at all.\n //\n // The cause is almost always an encoding, not a keystroke. UTF-16 read as\n // UTF-8 puts a NUL between every character, and the document that produces\n // looks plausible in some editors and is mojibake everywhere else.\n problems.push({\n message: `contains a NUL byte, so grep, diff and review tooling read this file as binary - check whether it was saved as UTF-16`,\n at: at(nul, nul + 1),\n });\n }\n\n // CommonMark reads a comment that opens a line and never closes as running\n // to the end of the document, and so does the scan: nothing after it is a\n // heading, an item or a link. A renderer hides it all, so the author may see\n // it, but the graph would lose it without a word.\n const unclosed = scanned.comments.find((comment) => !comment.closed);\n if (unclosed !== undefined) {\n problems.push({\n message: 'a comment opened here is never closed, so nothing after it is read - close it with -->',\n at: at(unclosed.start, unclosed.start + 4),\n });\n }\n\n for (const directive of directives) {\n for (const unknown of directive.unknownAttributes) {\n problems.push({\n message: `unknown attribute \"${unknown}\" on @${directive.name}`,\n at: at(directive.start, directive.end),\n });\n }\n }\n\n const { entries, problems: unread } = readEntries(scanned);\n for (const problem of unread) {\n // A line that names no key could have held any of them, and so could a\n // block that was not read at all.\n const lost = problem.unread && (problem.key === null || buildsGraph(problem.key));\n problems.push({ message: problem.message, at: at(problem.start, problem.end), ...(lost ? { unread: true } : {}) });\n }\n const byKey = new Map<string, YamlEntry>();\n for (const entry of entries) byKey.set(entry.key, entry);\n const inherited = inheritableFrontMatter(entries);\n\n const h1 = scanned.headings.find((h) => h.level === 1) ?? null;\n const frontMatterId = firstValue(byKey, ID_KEYS) ?? null;\n\n const identityOf = (declaredId: string | null, directive: Directive | null): DocumentIdentity =>\n identify({\n path: input.path,\n declaredId,\n declaredAliases: [\n ...(directive ? attrList(directive, 'aliases') : []),\n ...valuesOf(byKey.get('aliases')),\n ...valuesOf(byKey.get('alias')),\n ],\n heading: h1?.text ?? null,\n });\n\n // A `@spec-node` written inside a register's section belongs to that section,\n // not to the file. Finding the file's own therefore needs the regions, and\n // finding the regions needs the file's identity - so the identity is settled\n // provisionally first, then again once the file's own directive is known.\n const provisional = identityOf(frontMatterId, null);\n const provisionalRegions = findSpecificationRegions(scanned, directives, provisional.id);\n const nodeDirective =\n directives.find(\n (directive) =>\n directive.name === 'spec-node' &&\n !provisionalRegions.some(\n // `>=` and `>` agree on the start: a region starts at a heading's\n // first character or a row's, and a line that opens with a comment is\n // neither a heading nor a row.\n (region) =>\n (region.heading !== null || region.row !== null) &&\n directive.start >= region.start &&\n directive.end <= region.end,\n ),\n ) ?? null;\n\n const declaredId = (nodeDirective ? attr(nodeDirective, 'id')?.value : null) ?? frontMatterId;\n // With no directive of its own the file's identity is the provisional one,\n // computed from exactly these inputs. Settling it again would give the same\n // answer, which is why no test can tell this reuse from a second call.\n const identity = nodeDirective === null ? provisional : identityOf(declaredId, nodeDirective);\n\n // A register's sections are specifications too. The file is always the first\n // region, so a one-decision file behaves exactly as it did before. The regions\n // depend on the file's id alone, so when the directive left it unchanged the\n // provisional ones are the answer, and finding them again is the same answer.\n const regions =\n identity.id === provisional.id ? provisionalRegions : findSpecificationRegions(scanned, directives, identity.id);\n\n const status = readStatus(scanned, byKey, nodeDirective, index, file, regions);\n const pathPhase = phaseFromPath(input.path);\n // A record is a categorical statement about what the file *is*, made by\n // configuration or by an explicit directive, so it outranks a status word\n // that happened to be written inside it.\n const record = input.record === true || directives.some((directive) => directive.name === 'spec-history');\n const phase: Phase = record ? 'record' : status.phase !== 'unknown' ? status.phase : pathPhase;\n\n const title =\n (nodeDirective ? attr(nodeDirective, 'title')?.value : null) ??\n asString(byKey.get('title')) ??\n h1?.text ??\n identity.id;\n\n const document: DocumentNode = {\n id: identity.id,\n kind: 'document',\n title,\n at: at(0, Math.min(scanned.text.length, index.lineEnd(1))),\n path: input.path,\n aliases: identity.aliases,\n phase,\n history: record,\n rawStatus: status.raw,\n statusAt: status.at,\n frontMatter: toRecord(entries),\n };\n\n // Every region but the first: a heading section, or a row of a register kept\n // as a table.\n const subSpecifications = regions\n .filter((region) => region.heading !== null || region.row !== null)\n .map((region) =>\n buildRegion({\n region,\n containerId: identity.id,\n input,\n scanned,\n directives,\n index,\n file,\n pathPhase,\n record,\n inherited,\n }),\n );\n\n // The specification that owns an offset: the innermost region around it, or\n // the file when no region holds it and `regionAt` answers `null`.\n const documentAt = (offset: number): DocumentNode => {\n const region = regionAt(regions, offset);\n return subSpecifications.find((spec) => spec.region === region)?.document ?? document;\n };\n const ownerAt = (offset: number): string => documentAt(offset).id;\n\n const allItems = extractItems({ scanned, directives, ownerAt, file, index });\n\n const allReferences = extractReferences({\n scanned,\n directives,\n document,\n documentAt,\n items: allItems,\n byKey,\n status,\n claimed: regions.flatMap((region) => [...region.claimed]),\n file,\n index,\n });\n\n // Hand each region the items and references that fall inside it.\n const ownItems = allItems.filter((item) => item.document === identity.id);\n const ownReferences = allReferences.filter((reference) => belongsTo(reference, identity.id, allItems));\n const misreadKeys = misreadRelationKeys(byKey, identity.id, at);\n const anchors = anchorsOf(scanned.headings);\n\n const filled = subSpecifications.map((spec) => ({\n ...spec.extracted,\n items: allItems.filter((item) => item.document === spec.document.id),\n references: [\n // Column-declared relations first: they are typed by the header rather\n // than guessed from prose.\n ...spec.extracted.references,\n ...allReferences.filter((reference) => belongsTo(reference, spec.document.id, allItems)),\n ],\n }));\n\n return {\n document,\n items: ownItems,\n references: ownReferences,\n problems,\n misreadKeys,\n anchors,\n identity,\n scanned,\n subSpecifications: filled,\n containerId: null,\n };\n}\n\n/** True when a reference was written on a document or on one of its items. */\nfunction belongsTo(reference: ReferenceCandidate, documentId: string, items: readonly ItemNode[]): boolean {\n if (reference.from === documentId) return true;\n const owner = items.find((item) => item.id === reference.from);\n return owner?.document === documentId;\n}\n\ninterface RegionInput {\n readonly region: SpecificationRegion;\n readonly containerId: string;\n readonly input: ExtractInput;\n readonly scanned: ScannedDocument;\n readonly directives: readonly Directive[];\n readonly index: LineIndex;\n readonly file: string;\n readonly pathPhase: Phase;\n /** The whole file is a historical record, so every part of it is one too. */\n readonly record: boolean;\n /** The file's front matter, minus the keys a region must answer itself. */\n readonly inherited: Readonly<Record<string, string | readonly string[]>>;\n}\n\ninterface BuiltRegion {\n readonly region: SpecificationRegion;\n readonly document: DocumentNode;\n readonly extracted: ExtractedDocument;\n}\n\n/**\n * Turns one region into a specification.\n *\n * It produces exactly the `DocumentNode` a whole file produces, which is the\n * reason every rule, query and reporter works on registers without knowing they\n * exist. The only deliberate differences: the node is anchored at its heading\n * rather than at line one, it carries the file's front matter rather than front\n * matter of its own, and it does not claim the file's path as an alias - the\n * file already does, and two nodes answering to one path would make every link\n * to that file ambiguous.\n */\nfunction buildRegion(context: RegionInput): BuiltRegion {\n const { region, input, scanned, index, file, pathPhase, record, inherited } = context;\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n const identity = identify({\n path: input.path,\n declaredId: region.declaredId,\n declaredAliases: region.directive ? attrList(region.directive, 'aliases') : [],\n heading: region.title,\n includePathAliases: false,\n });\n\n const declaredStatus = region.directive ? attr(region.directive, 'status') : null;\n const rawStatus = declaredStatus?.value ?? region.status?.text ?? null;\n const statusAt = declaredStatus\n ? at(declaredStatus.start, declaredStatus.end)\n : region.status\n ? at(region.status.start, region.status.end)\n : null;\n const declaredPhase = phaseOf(rawStatus);\n\n const document: DocumentNode = {\n id: identity.id,\n kind: 'document',\n title: (region.directive ? attr(region.directive, 'title')?.value : null) ?? region.title ?? identity.id,\n // Anchored at its heading, or at the row when the register is a table. Every\n // region here has one or the other, so neither `?.` ever stops the chain.\n at: at(region.start, Math.min(region.end, region.heading?.end ?? region.row?.end ?? region.end)),\n path: input.path,\n aliases: identity.aliases,\n // A section of a journal is part of the journal, whatever status word it\n // wrote for itself. Being a record is a statement about the file made from\n // outside it, and it does not stop at a heading.\n phase: record ? 'record' : declaredPhase !== 'unknown' ? declaredPhase : pathPhase,\n history: record,\n rawStatus,\n statusAt,\n frontMatter: inherited,\n };\n\n const anchors = anchorsOf(scanned.headings.filter((h) => h.start >= region.start && h.start < region.end));\n\n // Relations a table declares by column, typed by the header the author wrote.\n const references: ReferenceCandidate[] = region.relations.map((relation) => ({\n kind: relation.kind,\n from: document.id,\n target: relation.target,\n origin: 'front-matter' as const,\n declaredAt: at(relation.start, relation.end),\n raw: `${relation.column}: ${relation.target}`,\n inverted: relation.inverted,\n opportunistic: false,\n }));\n\n return {\n region,\n document,\n extracted: {\n document,\n // Never read: the file's extraction replaces it once every item's owner\n // is known.\n items: [],\n references,\n problems: [],\n // The file has already reported anything misread at the top of it, and\n // there is one file however many regions it holds.\n misreadKeys: [],\n anchors,\n identity,\n scanned,\n subSpecifications: [],\n containerId: context.containerId,\n },\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Status */\n/* -------------------------------------------------------------------------- */\n\ninterface StatusReading {\n readonly raw: string | null;\n readonly at: SourceRef | null;\n readonly phase: Phase;\n}\n\n/**\n * Finds the document status.\n *\n * Looks in the places teams actually put it, in descending order of how\n * deliberate each is: a directive, a front-matter field, then the body of a\n * `## Status` section or a key-value table above the first section. A\n * repository using none of them still gets a phase from its directory layout,\n * which is handled by the caller.\n *\n * A status section inside a register's region is that region's, not the\n * file's. Read as the file's, a register whose first decision said\n * `### Status` / `Superseded by ADR-0009` was itself retired, and itself\n * superseded by ADR-0009, for something one of its decisions said.\n */\nfunction readStatus(\n scanned: ScannedDocument,\n byKey: ReadonlyMap<string, YamlEntry>,\n nodeDirective: Directive | null,\n index: LineIndex,\n file: string,\n regions: readonly SpecificationRegion[],\n): StatusReading {\n if (nodeDirective) {\n const declared = attr(nodeDirective, 'status');\n if (declared) {\n return {\n raw: declared.value,\n at: refOf(file, index, declared.start, declared.end),\n phase: phaseOf(declared.value),\n };\n }\n }\n\n for (const key of STATUS_KEYS) {\n const entry = byKey.get(key);\n if (!entry) continue;\n const raw = typeof entry.value === 'string' ? entry.value : entry.value.join(', ');\n if (raw.trim().length === 0) continue;\n return {\n raw,\n at: refOf(file, index, entry.valueStart, entry.end),\n phase: phaseOf(raw),\n };\n }\n\n const heading = scanned.headings.find((h) => isStatusHeading(h.text) && regionAt(regions, h.start) === null);\n if (heading) {\n const body = statusSectionBody(scanned, heading.line);\n if (body) {\n return {\n raw: body.text,\n at: refOf(file, index, body.start, body.end),\n phase: phaseOf(body.text),\n };\n }\n }\n\n const cell = statusTableCell(scanned);\n if (cell) {\n return {\n raw: cell.text,\n at: refOf(file, index, cell.start, cell.end),\n phase: phaseOf(cell.text),\n };\n }\n\n return { raw: null, at: null, phase: 'unknown' };\n}\n\n/** The left cells that make a two-column table's row the document's status. */\nconst STATUS_TABLE_KEYS: ReadonlySet<string> = new Set(['status', 'state']);\n\n/**\n * The status a key-value table at the top of a document gives:\n * `| Status | Accepted |`, as the right cell of the first row whose left cell\n * is a status key, the header row included.\n *\n * Read only where a document describes itself. A table under a heading below\n * the title is a legend or a register, and one with more than two columns is\n * not a list of the document's fields; neither is its status. A table\n * spec-graph reads as a register is left to its rows. Ranked with a `## Status`\n * section, after one: a document that has both is read from the section.\n */\nfunction statusTableCell(scanned: ScannedDocument): TableCell | null {\n const body = scanned.headings.find((h) => h.level >= 2)?.start ?? scanned.text.length;\n for (const table of scanned.tables) {\n // Tables come in order, and none starts on a heading's line, so `>` would\n // stop at the same table.\n if (table.start >= body) break;\n if (table.headers.length !== 2 || isRegisterTable(table)) continue;\n for (const cells of [table.headers, ...table.rows.map((row) => row.cells)]) {\n // A row always has a first cell: a line with no cell ends the table.\n const key = cells[0] as TableCell;\n const value = cells[1];\n // A row written short, or with nothing on the right, declares nothing.\n if (value === undefined || value.text.length === 0) continue;\n if (STATUS_TABLE_KEYS.has(key.text.replace(/[*_]/g, '').toLowerCase())) return value;\n }\n }\n return null;\n}\n\n/** The first non-blank line under a `## Status` heading. */\nfunction statusSectionBody(\n scanned: ScannedDocument,\n headingLine: number,\n): { text: string; start: number; end: number } | null {\n for (const line of scanned.lines) {\n if (line.line <= headingLine) continue;\n if (line.blank || isOnlyComment(scanned, line)) continue;\n if (!isMarkdownLine(line)) return null;\n // A heading immediately after means the section is empty - a setext one\n // too, whose text line does not start with `#` and read as the status.\n if (opensHeading(scanned, line.line)) return null;\n const trimmed = line.content.trim();\n const offset = line.contentStart + line.content.indexOf(trimmed);\n // Bullet lists under Status are a status history; take the first entry.\n const cleaned = trimmed.replace(/^[-*+]\\s+/, '');\n const start = offset + (trimmed.length - cleaned.length);\n return { text: cleaned, start, end: start + cleaned.length };\n }\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Items */\n/* -------------------------------------------------------------------------- */\n\ninterface ItemContext {\n readonly scanned: ScannedDocument;\n readonly directives: readonly Directive[];\n /** The specification that owns an offset, which in a register is a section. */\n readonly ownerAt: (offset: number) => string;\n readonly file: string;\n readonly index: LineIndex;\n}\n\nfunction extractItems(context: ItemContext): ItemNode[] {\n const { scanned, directives, ownerAt, file, index } = context;\n const out: ItemNode[] = [];\n const ordinals = new Map<string, number>();\n const bound = bindItemDirectives(scanned, directives);\n\n for (const item of scanned.listItems) {\n const section = sectionPathAt(scanned, item.start);\n const inObligationSection = section.some((heading) => OBLIGATION_SECTIONS.has(normaliseHeading(heading)));\n const directive = bound.get(item) ?? null;\n\n if (!isObligation(item, inObligationSection, directive)) continue;\n\n const documentId = ownerAt(item.start);\n const slug = section.length > 0 ? slugify(section[section.length - 1] as string) : 'item';\n // Ordinals count within a specification, so two decisions in one register\n // each get their own `#open-questions.1` rather than sharing a sequence.\n const key = `${documentId}#${slug}`;\n const ordinal = (ordinals.get(key) ?? 0) + 1;\n ordinals.set(key, ordinal);\n\n const declaredId = directive ? attr(directive, 'id')?.value : null;\n const id = `${documentId}#${declaredId ?? `${slug}.${ordinal}`}`;\n\n const state = resolveItemState({\n file,\n index,\n item,\n section,\n directive,\n inObligationSection,\n });\n\n out.push({\n id,\n kind: 'item',\n title: (directive ? attr(directive, 'title')?.value : null) ?? summarise(item.firstLine),\n at: refOf(file, index, item.start, item.end),\n declared: declaredId !== null && declaredId !== undefined,\n document: documentId,\n section,\n text: summarise(item.firstLine),\n body: item.body,\n disposition: state.disposition,\n openness: state.openness,\n evidence: state.evidence,\n conflicts: state.conflicts,\n });\n }\n\n return out;\n}\n\n/**\n * Decides whether a bullet is an obligation.\n *\n * A checkbox or an explicit directive always makes one. Otherwise only\n * top-level bullets under a heading like \"Open Questions\" count: promoting\n * every bullet in a specification would bury the real obligations under the\n * document's own prose.\n */\nfunction isObligation(item: ListItem, inObligationSection: boolean, directive: Directive | null): boolean {\n if (directive !== null) return true;\n if (item.checkbox !== null) return true;\n return inObligationSection && item.depth === 0;\n}\n\n/** The heading path enclosing an offset, outermost first. */\nfunction sectionPathAt(scanned: ScannedDocument, offset: number): string[] {\n const path: { level: number; text: string }[] = [];\n for (const heading of scanned.headings) {\n // A heading opening exactly at the offset would be a reference or an item\n // starting on a `#` or on the first word of a setext heading - and a heading\n // that begins with a reference is no section name either way.\n if (heading.start > offset) break;\n while (path.length > 0 && (path[path.length - 1] as { level: number }).level >= heading.level) path.pop();\n path.push({ level: heading.level, text: heading.text });\n }\n return path.map((entry) => entry.text);\n}\n\n/**\n * Memoised because it is called for every heading above every reference and\n * every item, and a corpus has only a handful of distinct headings - `Context`,\n * `Decision`, `Open Questions`, `See also` - repeated thousands of times.\n *\n * The cache changes how fast an answer arrives and never the answer, so no test\n * can see whether it is consulted, filled or bounded.\n */\nconst headingCache = new Map<string, string>();\n\nfunction normaliseHeading(text: string): string {\n const cached = headingCache.get(text);\n if (cached !== undefined) return cached;\n const normalised = text\n .toLowerCase()\n .replace(/[`*_~]/g, '')\n .replace(/[^\\p{L}\\p{N}\\s-]/gu, '')\n .replace(/\\s+/g, ' ')\n .trim();\n // Bounded so a pathological corpus of unique headings cannot grow it forever.\n if (headingCache.size < 4096) headingCache.set(text, normalised);\n return normalised;\n}\n\n/**\n * One-line form of an item for reports.\n *\n * Link syntax is flattened to its label. A finding that quotes the obligation\n * back at the reader should read like the sentence they wrote, not like the\n * Markdown source of it.\n */\nfunction summarise(text: string): string {\n const flat = text\n // An image first, so that a badge wrapped in a link, `[![icon](i.png)](x)`,\n // leaves `[icon](x)` for the link's pattern rather than a stray `![icon](x)`.\n .replace(/!\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n // `[[target|display]]` keeps the display half: that is the text a reader\n // of the rendered document actually sees.\n .replace(/\\[\\[(?:[^\\]|]*\\|)?([^\\]]*)\\]\\]/g, '$1')\n .replace(/\\s+/g, ' ')\n .trim();\n return flat.length <= 120 ? flat : `${flat.slice(0, 117)}...`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* References */\n/* -------------------------------------------------------------------------- */\n\ninterface ReferenceContext {\n readonly scanned: ScannedDocument;\n readonly directives: readonly Directive[];\n readonly document: DocumentNode;\n /** The specification that owns an offset, for a reference outside any item. */\n readonly documentAt: (offset: number) => DocumentNode;\n readonly items: readonly ItemNode[];\n readonly byKey: ReadonlyMap<string, YamlEntry>;\n readonly status: StatusReading;\n /** Cell ranges already typed by a table column header. */\n readonly claimed: readonly { start: number; end: number }[];\n readonly file: string;\n readonly index: LineIndex;\n}\n\n/**\n * True when an offset falls in a cell a column header already accounted for.\n *\n * Whether the end is in or out decides nothing: what sits there is the cell's\n * closing pipe or the space before it, and no reference starts on either.\n */\nfunction isClaimed(claimed: readonly { start: number; end: number }[], offset: number): boolean {\n return claimed.some((range) => offset >= range.start && offset < range.end);\n}\n\nfunction extractReferences(context: ReferenceContext): ReferenceCandidate[] {\n const { scanned, directives, document, documentAt, items, byKey, status, claimed, file, index } = context;\n // This list and the one `withoutOverlaps` builds from it are only ever read\n // through `belongsTo`, which passes nothing that was not written on a\n // document or one of its items: a stray entry in either would reach no one.\n const out: ReferenceCandidate[] = [];\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n // Front matter, walked in the order it was written rather than in the order\n // the vocabulary happens to be listed: a key the table does not know still has\n // to be looked at, and only the document knows which those are.\n for (const [key, entry] of byKey) {\n const relation = RELATION_INDEX.get(foldRelationKey(key));\n if (!relation) continue;\n for (const value of valuesOf(entry)) {\n const target = cleanTarget(value);\n if (target.length === 0) continue;\n out.push({\n kind: relation.kind,\n from: document.id,\n target,\n origin: 'front-matter',\n declaredAt: at(entry.valueStart, entry.end),\n raw: `${key}: ${value}`,\n inverted: relation.inverted,\n opportunistic: false,\n });\n }\n }\n\n // `status: Superseded by ADR-0009` is the most common supersession record of\n // all, and it never appears as a field of its own. A reading carries its text\n // and its place together or neither, so either test alone would do.\n if (status.raw && status.at) {\n for (const target of supersessionTargetsIn(status.raw)) {\n const cleaned = cleanTarget(target);\n if (cleaned.length === 0) continue;\n out.push({\n kind: 'supersedes',\n from: document.id,\n target: cleaned,\n origin: 'front-matter',\n declaredAt: status.at,\n raw: status.raw,\n inverted: true,\n opportunistic: true,\n });\n }\n }\n\n // Explicit edge directives.\n for (const directive of directives) {\n if (directive.name !== 'spec-edge') continue;\n const kind = attr(directive, 'kind')?.value as EdgeKind | undefined;\n const to = attr(directive, 'to');\n const from = attr(directive, 'from');\n if (!kind) continue;\n const owner = ownerOf(items, directive.start) ?? documentAt(directive.start).id;\n if (to) {\n out.push({\n kind,\n from: owner,\n target: to.value,\n origin: 'directive',\n declaredAt: at(to.start, to.end),\n raw: `@spec-edge kind=\"${kind}\" to=\"${to.value}\"`,\n inverted: false,\n opportunistic: false,\n });\n }\n if (from) {\n out.push({\n kind,\n from: owner,\n target: from.value,\n origin: 'directive',\n declaredAt: at(from.start, from.end),\n raw: `@spec-edge kind=\"${kind}\" from=\"${from.value}\"`,\n inverted: true,\n opportunistic: false,\n });\n }\n }\n\n // Prose links. A cell whose meaning a column header already gave is skipped,\n // so `| ADR-0002 | ... | [ADR-0001](0001.md) |` yields one typed edge rather\n // than a typed edge and a neutral citation beside it.\n const linked = new Set<string>();\n const links = referenceLinks(scanned);\n for (const link of links) {\n if (link.form === 'definition') continue;\n if (isClaimed(claimed, link.start)) continue;\n const target = cleanTarget(link.target);\n if (target.length === 0) continue;\n if (isExternal(target)) continue;\n\n const owner = ownerOf(items, link.start) ?? documentAt(link.start).id;\n const section = sectionPathAt(scanned, link.start);\n const classified = classifyReference(scanned.masks.structure, link.start, link.end, section);\n\n linked.add(normaliseRef(stripAnchor(target)));\n out.push({\n kind: classified.kind,\n from: owner,\n target,\n origin: 'link',\n declaredAt: at(link.targetStart, link.targetEnd),\n raw: renderLink(link),\n inverted: classified.inverted,\n opportunistic: false,\n });\n }\n\n // Bare identifiers in prose. Everything already covered by a link is skipped\n // so a citation written as `[ADR-7](0007.md)` is not counted twice.\n for (const bare of findBareReferences(scanned, links)) {\n const key = normaliseRef(bare.text);\n if (linked.has(key)) continue;\n if (isClaimed(claimed, bare.start)) continue;\n const owner = ownerOf(items, bare.start) ?? documentAt(bare.start).id;\n const section = sectionPathAt(scanned, bare.start);\n const classified = classifyReference(scanned.masks.structure, bare.start, bare.end, section);\n out.push({\n kind: classified.kind,\n from: owner,\n target: bare.text,\n origin: 'text',\n declaredAt: at(bare.start, bare.end),\n raw: bare.text,\n inverted: classified.inverted,\n opportunistic: true,\n });\n }\n\n return withoutOverlaps(out);\n}\n\n/**\n * Collapses candidates that describe the same written citation.\n *\n * `Superseded by ADR-0009` in a status section is read twice: the status\n * reader reports the whole line, and prose scanning reports the identifier\n * inside it. One written citation is one reference - so when the target\n * resolves it must not become two edges, and when it does not it must not\n * become two findings on one line a reader can only fix once.\n *\n * The narrower span wins, because it points at the text that has to change.\n *\n * Only overlapping spans collapse. Two sentences citing the same missing\n * document are two citations, and silently reporting one of them would leave\n * the other to be discovered on the next run.\n */\nfunction withoutOverlaps(candidates: readonly ReferenceCandidate[]): ReferenceCandidate[] {\n const out: ReferenceCandidate[] = [];\n for (const candidate of candidates) {\n // Today the only readings that can overlap are a status line and the prose\n // inside it, by one owner, and where they disagree they disagree on kind and\n // direction together. So the kind, owner and direction tests below cannot\n // be told apart one by one; each is here for a reader that differs in one.\n const index = out.findIndex(\n (other) =>\n other.kind === candidate.kind &&\n other.from === candidate.from &&\n other.inverted === candidate.inverted &&\n normaliseRef(other.target) === normaliseRef(candidate.target) &&\n overlapping(other.declaredAt, candidate.declaredAt),\n );\n if (index === -1) {\n out.push(candidate);\n continue;\n }\n const held = out[index] as ReferenceCandidate;\n // The status reader runs before prose scanning, so today the wider span is\n // always the one already held and this comparison always replaces it. It is\n // written as a comparison rather than an unconditional swap because which\n // reader runs first is not a property worth depending on, and a mutant that\n // makes it unconditional is equivalent only by that accident. Two of the\n // same width that match are one value written twice in one list, alike in\n // everything, so which of them is kept cannot matter.\n if (width(candidate.declaredAt) < width(held.declaredAt)) out[index] = candidate;\n }\n return out;\n}\n\nconst width = (ref: SourceRef): number => ref.span.end.offset - ref.span.start.offset;\n\n/**\n * Whether two spans cover any of the same text.\n *\n * Offsets alone, with no file comparison: every candidate here was built from\n * one scan of one file, so there is no second file for them to be offsets into.\n * Spans that only touch never occur between two readings of one target, so\n * whether touching counts as overlapping decides nothing.\n */\nfunction overlapping(a: SourceRef, b: SourceRef): boolean {\n return a.span.start.offset < b.span.end.offset && b.span.start.offset < a.span.end.offset;\n}\n\n/**\n * The item whose block contains an offset, if any.\n *\n * An item's span runs from its indentation or list marker to the line break\n * that ends it, and no reference or directive starts on either, so both bounds\n * could be closed or open alike. Items arrive in document order, where a nested\n * item follows the one it nests in and never shares its start: the last item\n * that contains the offset is the innermost, which the comparison below says\n * rather than relies on.\n */\nfunction ownerOf(items: readonly ItemNode[], offset: number): string | null {\n let best: ItemNode | null = null;\n for (const item of items) {\n const span = item.at.span;\n if (offset < span.start.offset || offset >= span.end.offset) continue;\n if (best === null || span.start.offset > best.at.span.start.offset) best = item;\n }\n return best?.id ?? null;\n}\n\nexport interface Classification {\n readonly kind: EdgeKind;\n readonly inverted: boolean;\n}\n\n/**\n * Decides what a reference means from the words around it.\n *\n * The nearest governing phrase within {@link VERB_WINDOW} characters wins, and\n * the search never crosses a sentence boundary. With nothing to go on, a\n * reference under a \"See also\" heading is bookkeeping and everything else is a\n * neutral citation.\n */\nexport function classifyReference(\n text: string,\n start: number,\n end: number,\n section: readonly string[],\n): Classification {\n const before = sentenceBefore(text, start);\n\n // Left to right, so the last match within the window is the nearest one - and\n // the nearest governing phrase is the one that governs.\n let best: Classification | null = null;\n VERB_PATTERN.lastIndex = 0;\n for (let m = VERB_PATTERN.exec(before); m !== null; m = VERB_PATTERN.exec(before)) {\n const phrase = m[0] as string;\n const end = (m.index ?? 0) + phrase.length;\n const distance = before.length - end;\n if (distance > VERB_WINDOW) continue;\n // What sits between the phrase and the reference has to be connective. A\n // negation in there reverses the claim the phrase would otherwise make.\n if (NEGATION.test(before.slice(end))) continue;\n // Always found: the pattern was compiled from this table's own keys, and a\n // lower-cased search matches them only as written. The check is for types.\n const rule = VERB_LOOKUP.get(phrase);\n if (rule) best = rule;\n }\n\n if (best) return best;\n\n // \"[ADR-0009] supersedes this decision\": the reference is the subject, so the\n // relation runs the other way.\n const after = sentenceAfter(text, end);\n for (const rule of VERB_RULES) {\n if (rule.inverted) continue;\n for (const phrase of rule.phrases) {\n if (!after.startsWith(phrase)) continue;\n if (rule.kind === 'assumes' || rule.kind === 'depends-on') continue;\n return { kind: rule.kind, inverted: true };\n }\n }\n\n // Any enclosing heading will do: a link under `### Notes` inside `## See also`\n // is bookkeeping still.\n for (const heading of section) {\n if (WEAK_SECTIONS.has(normaliseHeading(heading))) return { kind: 'relates-to', inverted: false };\n }\n\n return { kind: 'references', inverted: false };\n}\n\n/** A sentence end, a blank line, or the start of a new block-level item. */\n/**\n * A table cell edge ends a statement too.\n *\n * The pipe matters more than it looks. A table row is a list of independent\n * fields, and without it the look-behind window reaches back across the row\n * boundary into the previous row's prose. An index of archived documents whose\n * last column ended \"...before assuming the drift was fixed\" turned every\n * following row's link into an `assumes` edge, and so turned every archived\n * document it listed into a stale premise.\n *\n * A sentence written in Chinese ends at `。?!;`, with a space after it or\n * none, since Chinese writes none. A stop only ends a statement sooner, so it\n * reads fewer relations and never more: without it,\n * `Deferred to later。另見 ADR-0002` handed the question to ADR-0002 from the\n * sentence before.\n */\nconst STATEMENT_BREAK = /[.?!;]\\s|[。?!;]|\\n\\s*\\n|\\n\\s*[-*+>#]|\\|/g;\n\n/**\n * Lower-cased, whitespace-collapsed text back to the start of the statement.\n *\n * The search stops at the last boundary: a governing phrase in the *previous*\n * sentence does not govern this reference. \"We deferred that to ADR-3. See also\n * [ADR-9].\" must not read as a delegation to ADR-9.\n */\nfunction sentenceBefore(text: string, start: number): string {\n const window = text.slice(Math.max(0, start - 160), start);\n let cut = 0;\n STATEMENT_BREAK.lastIndex = 0;\n for (let m = STATEMENT_BREAK.exec(window); m !== null; m = STATEMENT_BREAK.exec(window)) {\n cut = (m.index ?? 0) + (m[0] as string).length;\n }\n return window\n .slice(cut)\n .toLowerCase()\n .replace(/[`*_~\"'()\\[\\],]/g, ' ')\n .replace(/\\s+/g, ' ');\n}\n\n/**\n * The statement after a reference, to the first stop, the stops of a sentence\n * written in Chinese included.\n *\n * Only its start is read. A line break matters as a stop, since the trim\n * below would otherwise bring the next line's phrase to the start. A Chinese\n * stop is never trimmed, so a phrase after one cannot start the text either\n * way, and the mutants that drop one are equivalent: it is here so the\n * statement is the one `sentenceBefore` reads.\n */\nfunction sentenceAfter(text: string, end: number): string {\n const window = text.slice(end, Math.min(text.length, end + 80));\n const stop = /[.?!;\\n|。?!;]/.exec(window);\n const cut = stop ? window.slice(0, stop.index) : window;\n return cut.toLowerCase().replace(/[`*_~\"'()\\[\\],]/g, ' ').replace(/\\s+/g, ' ').trim();\n}\n\ninterface BareReference {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\n/**\n * Finds identifiers written as plain prose, such as \"as decided in ADR-0007\".\n *\n * Link constructs are blanked first. Without that, `[ADR-7](https://x/adr-7)`\n * would yield three references to the same thing - one real and two harvested\n * out of a URL - which is precisely the mis-match that makes hand-rolled regex\n * checks untrustworthy. Images are not blanked, since they are not references:\n * an identifier in one's text is prose, as it always was here.\n */\nfunction findBareReferences(scanned: ScannedDocument, links: readonly Link[]): BareReference[] {\n // Slice-based for the same reason as the scanner's masking: this runs over\n // every document, and a per-character array is the wrong shape for the job.\n const source = scanned.masks.structure;\n let text = '';\n let cursor = 0;\n for (const link of links) {\n const start = Math.max(link.start, cursor);\n const end = Math.min(link.end, source.length);\n // Links from one scan come in order and never nest, so this skips nothing\n // today. It keeps a scanner that did nest them from copying text twice.\n if (end <= start) continue;\n text += source.slice(cursor, start);\n text += source.slice(start, end).replace(/[^\\n\\r]/g, ' ');\n cursor = end;\n }\n text += source.slice(cursor);\n\n const out: BareReference[] = [];\n BARE_REF.lastIndex = 0;\n for (let m = BARE_REF.exec(text); m !== null; m = BARE_REF.exec(text)) {\n const written = m[0];\n // The family as resolution will read it, which takes the shortest prefix\n // the number allows: `base64` is `base` and 64. Read off this pattern's\n // greedy prefix it was `base6` and 4, and `ES2015`, `ARM64` and `Win32`\n // walked past the list below as families of their own. Every match is a\n // prefixed identifier by construction, so the parse cannot fail.\n const family = (parsePrefixedRef(written) as { family: string }).family.toLowerCase();\n if (NOT_A_FAMILY.has(family)) continue;\n if (family.length < 2) continue;\n const start = m.index;\n // A token glued to a path separator or an extension is not a citation. At\n // either end of the text the stand-in need only be neither `/` nor `.`.\n const before = text[start - 1] ?? ' ';\n const after = text[start + written.length] ?? ' ';\n if (before === '/' || before === '.' || after === '/') continue;\n out.push({ text: written, start, end: start + written.length });\n }\n return out;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction firstValue(byKey: ReadonlyMap<string, YamlEntry>, keys: readonly string[]): string | null {\n for (const key of keys) {\n // A key that is missing reads as null, the same as a blank one.\n const value = asString(byKey.get(key));\n if (value !== null && value.length > 0) return value;\n }\n return null;\n}\n\nfunction asString(entry: YamlEntry | undefined): string | null {\n if (!entry) return null;\n if (typeof entry.value === 'string') return entry.value.trim().length > 0 ? entry.value.trim() : null;\n return entry.value.length > 0 ? (entry.value[0] as string) : null;\n}\n\n/** Strips Markdown decoration a target may still be wearing. */\nfunction cleanTarget(value: string): string {\n return value\n .trim()\n .replace(/^[`'\"<(\\[]+/, '')\n .replace(/[`'\">)\\]]+$/, '')\n .replace(/[.,;]+$/, '')\n .trim();\n}\n\nfunction stripAnchor(target: string): string {\n const hash = target.indexOf('#');\n return hash <= 0 ? target : target.slice(0, hash);\n}\n\n/**\n * A link's text for an edge's `raw`.\n *\n * An autolink never reaches here: spec-core reads one only when it carries a\n * scheme, and a link with a scheme is external and was dropped before this. A\n * reference or shortcut link always has a label, so the `''` is for the type.\n */\nfunction renderLink(link: Link): string {\n switch (link.form) {\n case 'wiki':\n return `[[${link.target}]]`;\n case 'reference':\n case 'shortcut':\n return `[${link.text}][${link.label ?? ''}]`;\n default:\n return `[${link.text}](${link.target})`;\n }\n}\n\n/** Exposed for tests and for callers that classify their own sections. */\nexport { OBLIGATION_SECTIONS, sectionPathAt, WEAK_SECTIONS };\n"]}
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Document extraction: Markdown in, graph fragments out.\n *\n * This module is where domain-agnosticism is won or lost. It never requires a\n * repository to adopt a syntax. It reads what teams already write - front\n * matter, a `## Status` section, a checklist under `## Open Questions`, a link\n * that says \"deferred to ADR-0011\" - and turns each into a typed relation with a\n * source position.\n *\n * The one rule it holds to everywhere: **an inference that cannot be justified\n * is not made.** An unrecognised status becomes `unknown`, not a guess. A link\n * with no governing verb becomes a neutral `references`, not a dependency. Bare\n * identifiers found in prose are opportunistic and are dropped silently when\n * they do not resolve, because the alternative is reporting `SHA-256` as a\n * broken reference to specification 256.\n */\n\nimport { attr, attrList, bindItemDirectives, parseDirectives, type Directive } from './directives.js';\nimport {\n identify,\n isDocumentTarget,\n isExternal,\n looksLikePath,\n normaliseRef,\n parsePrefixedRef,\n withinOneEdit,\n type DocumentIdentity,\n ID_KEYS,\n} from './identity.js';\nimport { isStatusHeading, phaseFromPath, phaseOf, STATUS_KEYS, supersessionTargetsIn } from './lifecycle.js';\nimport {\n anchorsOf,\n isMarkdownLine,\n isOnlyComment,\n referenceLinks,\n scanMarkdown,\n slugify,\n type Link,\n type ListItem,\n type ScannedDocument,\n type TableCell,\n} from './markdown.js';\nimport {\n findSpecificationRegions,\n isRegisterTable,\n opensHeading,\n regionAt,\n type SpecificationRegion,\n} from './sections.js';\nimport { resolveItemState } from './state.js';\nimport { refOf, type LineIndex } from './source.js';\nimport type {\n DocumentNode,\n EdgeKind,\n EdgeOrigin,\n ItemNode,\n MisreadKey,\n ParseProblem,\n Phase,\n SourceRef,\n} from './types.js';\nimport { readEntries, toRecord, valuesOf, type YamlEntry } from './yaml.js';\n\n/* -------------------------------------------------------------------------- */\n/* Output */\n/* -------------------------------------------------------------------------- */\n\n/**\n * A relation that has been read but not yet resolved to a target node.\n *\n * Resolution needs the whole corpus, so extraction stops at the raw target text.\n */\nexport interface ReferenceCandidate {\n readonly kind: EdgeKind;\n /** Id of the node the relation was written on. */\n readonly from: string;\n /** The target exactly as written: a path, an identifier, or a URL. */\n readonly target: string;\n readonly origin: EdgeOrigin;\n readonly declaredAt: SourceRef;\n readonly raw: string;\n /**\n * When true the relation runs `target -> from`.\n *\n * `superseded-by: ADR-0009` written in ADR-0003 declares that *ADR-0009*\n * supersedes ADR-0003. The edge belongs to ADR-0009; the line a human must go\n * and fix is in ADR-0003, which is why `declaredAt` is tracked separately.\n */\n readonly inverted: boolean;\n /**\n * Opportunistic references are dropped in silence when they do not resolve.\n * Only deliberate ones - links, front matter, directives - are reported.\n */\n readonly opportunistic: boolean;\n}\n\nexport interface ExtractedDocument {\n readonly document: DocumentNode;\n readonly items: readonly ItemNode[];\n readonly references: readonly ReferenceCandidate[];\n readonly problems: readonly ParseProblem[];\n /**\n * Front-matter keys that read as relations and declared none.\n *\n * Kept apart from `problems` because a problem is about the text and this is\n * about the graph: the edge the author wrote down is not in it.\n */\n readonly misreadKeys: readonly MisreadKey[];\n /** Heading slugs and GitHub's anchors, for resolving `#anchor` references into this document. */\n readonly anchors: ReadonlySet<string>;\n readonly identity: DocumentIdentity;\n readonly scanned: ScannedDocument;\n /**\n * Specifications declared inside this file, each a document in its own right.\n *\n * Empty for the ordinary one-file-per-decision layout, which is why nothing\n * downstream had to change to support registers.\n */\n readonly subSpecifications: readonly ExtractedDocument[];\n /**\n * The file-level specification this one is a region of, if any.\n *\n * Recorded so the register's structure is a relation in the graph rather than\n * an accident of which offsets fall inside which: \"what decisions does this\n * register hold\" is a question worth being able to ask.\n */\n readonly containerId: string | null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Vocabulary */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Front-matter keys that declare a relation, and what they mean.\n *\n * Every directional kind is spelled in **both** directions. A register that\n * records `depends-on` but not `depended-on-by` is not a smaller vocabulary, it\n * is a trap: the author writes the inverse, the key means nothing, and the edge\n * they declared is missing from a graph that reports itself as consistent. Which\n * half of a pair a repository writes is a filing convention, and a filing\n * convention is not something a linter gets to have an opinion about.\n *\n * `relates-to` is the exception, and it is not one: the relation is symmetric,\n * so it has no other direction to spell. `contains` is structural and never\n * written by hand. `tests/parsing.test.ts` holds both facts to the fire.\n */\nexport const RELATION_KEYS: Readonly<Record<string, { kind: EdgeKind; inverted: boolean }>> = {\n supersedes: { kind: 'supersedes', inverted: false },\n supercedes: { kind: 'supersedes', inverted: false },\n replaces: { kind: 'supersedes', inverted: false },\n obsoletes: { kind: 'supersedes', inverted: false },\n deprecates: { kind: 'supersedes', inverted: false },\n 'superseded-by': { kind: 'supersedes', inverted: true },\n 'superceded-by': { kind: 'supersedes', inverted: true },\n 'replaced-by': { kind: 'supersedes', inverted: true },\n 'obsoleted-by': { kind: 'supersedes', inverted: true },\n 'deprecated-by': { kind: 'supersedes', inverted: true },\n 'rolled-into': { kind: 'supersedes', inverted: true },\n amends: { kind: 'amends', inverted: false },\n extends: { kind: 'amends', inverted: false },\n refines: { kind: 'amends', inverted: false },\n clarifies: { kind: 'amends', inverted: false },\n revises: { kind: 'amends', inverted: false },\n 'amended-by': { kind: 'amends', inverted: true },\n 'extended-by': { kind: 'amends', inverted: true },\n 'refined-by': { kind: 'amends', inverted: true },\n 'clarified-by': { kind: 'amends', inverted: true },\n 'revised-by': { kind: 'amends', inverted: true },\n 'depends-on': { kind: 'depends-on', inverted: false },\n 'dependent-on': { kind: 'depends-on', inverted: false },\n dependencies: { kind: 'depends-on', inverted: false },\n requires: { kind: 'depends-on', inverted: false },\n 'builds-on': { kind: 'depends-on', inverted: false },\n 'relies-on': { kind: 'depends-on', inverted: false },\n 'depended-on-by': { kind: 'depends-on', inverted: true },\n 'required-by': { kind: 'depends-on', inverted: true },\n dependents: { kind: 'depends-on', inverted: true },\n assumes: { kind: 'assumes', inverted: false },\n 'assumed-by': { kind: 'assumes', inverted: true },\n 'blocked-by': { kind: 'blocked-by', inverted: false },\n 'blocked-on': { kind: 'blocked-by', inverted: false },\n 'waiting-on': { kind: 'blocked-by', inverted: false },\n 'waiting-for': { kind: 'blocked-by', inverted: false },\n 'gated-on': { kind: 'blocked-by', inverted: false },\n 'gated-by': { kind: 'blocked-by', inverted: false },\n blocks: { kind: 'blocked-by', inverted: true },\n 'delegates-to': { kind: 'delegates-to', inverted: false },\n 'delegated-to': { kind: 'delegates-to', inverted: false },\n 'deferred-to': { kind: 'delegates-to', inverted: false },\n 'tracked-in': { kind: 'delegates-to', inverted: false },\n 'tracked-by': { kind: 'delegates-to', inverted: false },\n 'continued-in': { kind: 'delegates-to', inverted: false },\n 'delegated-from': { kind: 'delegates-to', inverted: true },\n related: { kind: 'relates-to', inverted: false },\n 'relates-to': { kind: 'relates-to', inverted: false },\n 'related-to': { kind: 'relates-to', inverted: false },\n 'see-also': { kind: 'relates-to', inverted: false },\n references: { kind: 'references', inverted: false },\n reference: { kind: 'references', inverted: false },\n refs: { kind: 'references', inverted: false },\n 'referenced-by': { kind: 'references', inverted: true },\n};\n\n/**\n * True when a front-matter value is shaped like a citation.\n *\n * The second half of the gate on {@link misreadRelationKeys}, and the half that\n * does the work. `sidebar_position: 4` and `ref: main` are a hair away from a\n * relation key by spelling alone; neither carries anything that could name a\n * document, and reporting them would make the rule an irritation rather than a\n * catch (ADR-0006).\n */\nfunction looksLikeCitation(value: string): boolean {\n // A blank value needs no case of its own: it is neither an identifier nor a\n // path, so both tests below already answer no.\n const trimmed = value.trim();\n if (parsePrefixedRef(trimmed) !== null) return true;\n return looksLikePath(trimmed) && isDocumentTarget(trimmed) && !isExternal(trimmed);\n}\n\n/**\n * Front-matter keys that read as relations and declare none.\n *\n * Front matter is an open vocabulary and most of what lives there is nobody\n * else's business, so the bar is deliberately high: the key has to be one edit\n * from a relation key *and* carry something that could name a document. Both\n * conditions together are what separates `dependson: ADR-0001`, which is an edge\n * the author believes exists, from `description: ...`, which is a title.\n */\nfunction misreadRelationKeys(\n byKey: ReadonlyMap<string, YamlEntry>,\n from: string,\n at: (start: number, end: number) => SourceRef,\n): MisreadKey[] {\n const out: MisreadKey[] = [];\n for (const [key, entry] of byKey) {\n const folded = foldRelationKey(key);\n // A key of nothing but punctuation folds to nothing. The shortest relation\n // key folds to four letters, so the edit test below would pass it over too\n // and no test can see this half; it keeps that true for any future key.\n if (folded.length === 0 || RELATION_INDEX.has(folded)) continue;\n if (!valuesOf(entry).some(looksLikeCitation)) continue;\n const near = [...RELATION_INDEX.values()]\n .filter((relation) => withinOneEdit(folded, foldRelationKey(relation.canonical)))\n .map((relation) => relation.canonical);\n if (near.length === 0) continue;\n out.push({ key, suggestion: near.join(', '), from, at: at(entry.start, entry.end) });\n }\n return out;\n}\n\n/**\n * Folds a front-matter key to its lookup form.\n *\n * `depends-on`, `depends_on`, `dependsOn` and `Depends On` are one key written\n * four ways, and which one a repository uses is decided by whatever wrote the\n * front matter first. Dropping every separator collapses them - the YAML reader\n * has already lower-cased the key, which is what makes camel case fold too.\n *\n * Which case this folds to is arbitrary and no test pins it: both sides of every\n * comparison come through here, so upper would work exactly as well. Asserting\n * on it would be asserting on the implementation.\n */\nexport function foldRelationKey(key: string): string {\n return key.replace(/[^a-z0-9]/gi, '').toLowerCase();\n}\n\n/** The vocabulary above, indexed by folded key. */\nconst RELATION_INDEX: ReadonlyMap<string, { kind: EdgeKind; inverted: boolean; canonical: string }> = new Map(\n Object.entries(RELATION_KEYS).map(([canonical, relation]) => [\n foldRelationKey(canonical),\n { ...relation, canonical },\n ]),\n);\n\n/**\n * Whether a front-matter key is one the graph is built from: a status, an id\n * or an alias, or a relation. Left unread, each changes a verdict - a status\n * is unknown, a node is named by its path, an edge is missing. A title or a\n * description left unread changes a label.\n */\nfunction buildsGraph(key: string): boolean {\n return (\n STATUS_KEYS.includes(key) ||\n ID_KEYS.includes(key) ||\n key === 'alias' ||\n key === 'aliases' ||\n RELATION_INDEX.has(foldRelationKey(key))\n );\n}\n\n/**\n * Keys a region must answer for itself, so the file's answer cannot shadow one.\n *\n * Identity and status and title are the three things a register exists to vary\n * row by row. The rest of the file's front matter describes the file, and a\n * decision inside the file is described by it too.\n */\nconst UNINHERITED: ReadonlySet<string> = new Set([...ID_KEYS, ...STATUS_KEYS, 'title', 'alias', 'aliases']);\n\n/**\n * The front matter a region inherits from the file that contains it.\n *\n * [ADR-0009](../docs/adr/0009-a-specification-is-a-region.md) left this open,\n * and [ADR-0016](../docs/adr/0016-a-query-needs-a-sentence.md) made leaving it\n * open a defect. A repository can now write `document[fm.owner!=platform]` as a\n * rule of its own, and on a register every region answered nothing - which\n * `!=` reads as a mismatch, because an absent value is not the value. A file\n * whose front matter said `owner: platform` was reported twice for not being\n * owned by platform, and the message rendered `{0.fm.owner}` as the literal\n * placeholder. Confident, wrong, and unanswerable: the ADR-0006 failure.\n *\n * Two kinds of key stay behind. A relation key is a claim the file made -\n * `supersedes:` at the top of a register supersedes on behalf of the register,\n * not on behalf of each decision in it, and the edges were built from the\n * file's entries before this ran. And a key the region answers itself must not\n * be shadowed, which is {@link UNINHERITED}.\n */\nexport function inheritableFrontMatter(\n entries: readonly YamlEntry[],\n): Readonly<Record<string, string | readonly string[]>> {\n return toRecord(\n entries.filter((entry) => !UNINHERITED.has(entry.key) && !RELATION_INDEX.has(foldRelationKey(entry.key))),\n );\n}\n\n/**\n * Phrases that give a link its meaning, longest-matching-nearest wins.\n *\n * Only phrases that genuinely commit the citing document are here. Vague ones\n * (\"see\", \"covered by\") stay out: a `references` edge is harmless, whereas a\n * wrongly inferred `assumes` edge produces a confident stale-premise finding\n * about a document that never depended on anything.\n */\nconst VERB_RULES: readonly { kind: EdgeKind; inverted: boolean; phrases: readonly string[] }[] = [\n {\n kind: 'supersedes',\n inverted: true,\n phrases: ['superseded by', 'superceded by', 'replaced by', 'obsoleted by', 'deprecated by', 'rolled into'],\n },\n { kind: 'supersedes', inverted: false, phrases: ['supersedes', 'supercedes', 'replaces', 'obsoletes', 'deprecates'] },\n { kind: 'amends', inverted: true, phrases: ['amended by', 'refined by', 'clarified by', 'revised by'] },\n { kind: 'amends', inverted: false, phrases: ['amends', 'refines', 'clarifies', 'revises'] },\n {\n kind: 'delegates-to',\n inverted: false,\n phrases: [\n 'delegated to',\n 'delegate to',\n 'deferred to',\n 'defer to',\n 'moved to',\n 'move to',\n 'tracked in',\n 'tracked by',\n 'handed off to',\n 'handed to',\n 'hand off to',\n 'follow up in',\n 'follow-up in',\n 'followup in',\n 'continued in',\n 'continues in',\n 'punted to',\n 'left to',\n 'belongs in',\n 'owned by',\n 'will be decided in',\n 'will be resolved in',\n 'will be handled in',\n 'will be handled by',\n 'will be answered in',\n 'to be decided in',\n 'to be resolved in',\n 'to be handled in',\n 'to be answered in',\n ],\n },\n {\n kind: 'blocked-by',\n inverted: false,\n phrases: ['blocked by', 'blocked on', 'waiting on', 'waiting for', 'gated on', 'gated by', 'unblocked by'],\n },\n { kind: 'blocked-by', inverted: true, phrases: ['blocks', 'blocking'] },\n {\n kind: 'depends-on',\n inverted: false,\n phrases: ['depends on', 'depend on', 'dependent on', 'requires', 'builds on', 'built on', 'relies on'],\n },\n { kind: 'depends-on', inverted: true, phrases: ['depended on by'] },\n {\n kind: 'assumes',\n inverted: false,\n phrases: [\n 'assumes',\n 'assuming',\n 'on the assumption of',\n 'as decided in',\n 'as established in',\n 'as established by',\n 'as stated in',\n 'as specified in',\n 'as required by',\n 'as mandated by',\n 'in accordance with',\n 'constrained by',\n 'mandated by',\n 'governed by',\n 'predicated on',\n 'rests on',\n 'follows from',\n 'justified by',\n // A constraint the citing document designs around. \"the row limit imposed\n // by ADR-0002\" is the archetypal stale premise: when ADR-0002 is retired,\n // this document is still working around a cap that no longer exists.\n 'imposed by',\n 'required by',\n 'dictated by',\n 'determined by',\n 'limited by',\n 'capped by',\n 'bounded by',\n 'defined by',\n 'defined in',\n 'specified by',\n 'set by',\n 'per',\n 'because',\n 'since',\n ],\n },\n];\n\n/**\n * Words that cancel a governing phrase standing before them.\n *\n * The window allows a short noun phrase between a verb and the reference it\n * governs - \"deferred to the sharding decision in [ADR-7]\" is one statement.\n * It cannot allow a negation. A table entry reading \"Owned by nobody today and\n * disclaimed by [138]\" was being read as a delegation *to* 138, which is the\n * opposite of what the sentence says, and an inference that inverts its source\n * is worse than no inference at all.\n *\n * The `^` never decides anything: the text tested starts just after a phrase,\n * and a phrase only matches where no letter follows it.\n */\nconst NEGATION = /(?:^|\\s)(?:no|not|nobody|none|never|neither|nor|nothing|without)(?:\\s|$)/;\n\n/** How close a governing phrase must sit to the reference it governs. */\nconst VERB_WINDOW = 40;\n\n/**\n * Every governing phrase compiled into one alternation, plus a lookup table.\n *\n * Classification runs on every reference in the corpus, and testing a hundred\n * phrases one at a time made it the most expensive thing extraction did. The\n * alternation is sorted longest-first so that at any given position the regex\n * prefers `partially resolved` over `resolved`, matching the precedence the\n * per-phrase search had. Lookarounds rather than `\\b`, because phrases contain\n * hyphens and `\\b` does the wrong thing around them.\n *\n * Neither the sort nor the escaping decides anything today, and no test can\n * pin them: no phrase in the table is another one followed by more words, and\n * none holds a character a pattern would read. Both are for the next phrase.\n */\nconst VERB_LOOKUP: ReadonlyMap<string, Classification> = new Map(\n VERB_RULES.flatMap((rule) =>\n rule.phrases.map((phrase) => [phrase, { kind: rule.kind, inverted: rule.inverted }] as const),\n ),\n);\n\nconst VERB_PATTERN = new RegExp(\n `(?<![\\\\p{L}\\\\p{N}])(?:${[...VERB_LOOKUP.keys()]\n .sort((a, b) => b.length - a.length)\n .map((phrase) => phrase.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n .join('|')})(?![\\\\p{L}\\\\p{N}])`,\n 'gu',\n);\n\n/** Headings under which a link is bookkeeping rather than a commitment. */\nconst WEAK_SECTIONS: ReadonlySet<string> = new Set([\n 'see also',\n 'references',\n 'reference',\n 'related',\n 'related work',\n 'related decisions',\n 'related documents',\n 'links',\n 'further reading',\n 'prior art',\n 'history',\n 'changelog',\n 'change log',\n 'revision history',\n 'bibliography',\n 'sources',\n 'appendix',\n 'more information',\n 'resources',\n 'index',\n]);\n\n/** Headings whose bullets are obligations even without a checkbox. */\nconst OBLIGATION_SECTIONS: ReadonlySet<string> = new Set([\n 'open questions',\n 'open question',\n 'unresolved questions',\n 'unanswered questions',\n 'questions',\n 'open issues',\n 'action items',\n 'actions',\n 'todo',\n 'to do',\n 'to-do',\n 'todos',\n 'next steps',\n 'follow ups',\n 'follow-ups',\n 'followups',\n 'follow up',\n 'follow-up',\n 'unresolved',\n 'outstanding',\n 'outstanding questions',\n 'tasks',\n 'task list',\n 'work items',\n 'remaining work',\n 'decisions needed',\n 'blockers',\n 'parking lot',\n 'future work',\n 'deferred',\n]);\n\n/**\n * Prefixes that look like specification identifiers but never are.\n *\n * The corpus filter in `resolve.ts` is the real defence; this list only keeps\n * the obvious noise out of the candidate set. A single letter - `v2`, `x86`,\n * `p99` - is not here because no prefix that short is ever read as a family.\n */\nconst NOT_A_FAMILY: ReadonlySet<string> = new Set([\n 'ver',\n 'version',\n 'pp',\n 'fig',\n 'figure',\n 'table',\n 'tbl',\n 'section',\n 'sect',\n 'sec',\n 'step',\n 'item',\n 'no',\n 'num',\n 'line',\n 'ln',\n 'col',\n 'port',\n 'pr',\n 'issue',\n 'gh',\n 'utf',\n 'ascii',\n 'sha',\n 'md',\n 'http',\n 'https',\n 'ipv',\n 'tls',\n 'ssl',\n 'es',\n 'ecma',\n 'p99',\n 'base',\n 'sql',\n 'ipv4',\n 'ipv6',\n 'arm',\n 'x86',\n 'win',\n 'node',\n 'python',\n 'java',\n 'go',\n 'cpp',\n]);\n\nconst BARE_REF = /\\b[A-Za-z][A-Za-z0-9]{0,14}[\\s._-]?\\d{1,6}\\b/g;\n\n/* -------------------------------------------------------------------------- */\n/* Extraction */\n/* -------------------------------------------------------------------------- */\n\nexport interface ExtractInput {\n /** Repository-relative POSIX path. */\n readonly path: string;\n readonly text: string;\n /**\n * This file is a historical record: a log of what was decided, not a\n * decision. Matched against the caller's history patterns, because deciding\n * which files those are is a repository's business and not a guess this\n * layer could justify making. See ADR-0011.\n */\n readonly record?: boolean | undefined;\n}\n\n/**\n * Reads one file into graph fragments, one entry per specification in it.\n *\n * A file yields at least itself. It yields more when it is a register: a\n * heading that carries an identifier *and* declares a status is a specification\n * in its own right, with its own lifecycle, its own obligations and its own\n * relations. See ADR-0009.\n */\nexport function extractSpecifications(input: ExtractInput): ExtractedDocument[] {\n const first = extractDocument(input);\n return first === null ? [] : [first, ...(first.subSpecifications as ExtractedDocument[])];\n}\n\n/** Reads a file's own specification. Returns `null` when it opts out. */\n/** The one character that makes a text file read as binary to other tools. */\nconst NUL = '\\u0000';\n\nexport function extractDocument(input: ExtractInput): ExtractedDocument | null {\n const scanned = scanMarkdown(input.text);\n const directives = parseDirectives(scanned.comments);\n if (directives.some((d) => d.name === 'spec-ignore')) return null;\n\n const index = scanned.index;\n const file = input.path;\n const problems: ParseProblem[] = [];\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n const nul = input.text.indexOf(NUL);\n if (nul !== -1) {\n // Not a finding. Nothing about the graph is wrong, and the text parsed - a\n // NUL is whitespace to every rule here. It is a problem with the *input*,\n // which is what a ParseProblem is for, and it is worth one line because\n // spec-graph is likely the only tool that got this far: grep, diff and\n // every review interface read the file as binary and show nothing at all.\n //\n // The cause is almost always an encoding, not a keystroke. UTF-16 read as\n // UTF-8 puts a NUL between every character, and the document that produces\n // looks plausible in some editors and is mojibake everywhere else.\n problems.push({\n message: `contains a NUL byte, so grep, diff and review tooling read this file as binary - check whether it was saved as UTF-16`,\n at: at(nul, nul + 1),\n });\n }\n\n // CommonMark reads a comment that opens a line and never closes as running\n // to the end of the document, and so does the scan: nothing after it is a\n // heading, an item or a link. A renderer hides it all, so the author may see\n // it, but the graph would lose it without a word.\n const unclosed = scanned.comments.find((comment) => !comment.closed);\n if (unclosed !== undefined) {\n problems.push({\n message: 'a comment opened here is never closed, so nothing after it is read - close it with -->',\n at: at(unclosed.start, unclosed.start + 4),\n });\n }\n\n for (const directive of directives) {\n for (const unknown of directive.unknownAttributes) {\n problems.push({\n message: `unknown attribute \"${unknown}\" on @${directive.name}`,\n at: at(directive.start, directive.end),\n });\n }\n }\n\n const { entries, problems: unread } = readEntries(scanned);\n for (const problem of unread) {\n // A line that names no key could have held any of them, and so could a\n // block that was not read at all.\n const lost = problem.unread && (problem.key === null || buildsGraph(problem.key));\n problems.push({ message: problem.message, at: at(problem.start, problem.end), ...(lost ? { unread: true } : {}) });\n }\n const byKey = new Map<string, YamlEntry>();\n for (const entry of entries) byKey.set(entry.key, entry);\n const inherited = inheritableFrontMatter(entries);\n\n const h1 = scanned.headings.find((h) => h.level === 1) ?? null;\n const frontMatterId = firstValue(byKey, ID_KEYS) ?? null;\n\n const identityOf = (declaredId: string | null, directive: Directive | null): DocumentIdentity =>\n identify({\n path: input.path,\n declaredId,\n declaredAliases: [\n ...(directive ? attrList(directive, 'aliases') : []),\n ...valuesOf(byKey.get('aliases')),\n ...valuesOf(byKey.get('alias')),\n ],\n heading: h1?.text ?? null,\n });\n\n // A `@spec-node` written inside a register's section belongs to that section,\n // not to the file. Finding the file's own therefore needs the regions, and\n // finding the regions needs the file's identity - so the identity is settled\n // provisionally first, then again once the file's own directive is known.\n const provisional = identityOf(frontMatterId, null);\n const provisionalRegions = findSpecificationRegions(scanned, directives, provisional.id);\n const nodeDirective =\n directives.find(\n (directive) =>\n directive.name === 'spec-node' &&\n !provisionalRegions.some(\n // `>=` and `>` agree on the start: a region starts at a heading's\n // first character or a row's, and a line that opens with a comment is\n // neither a heading nor a row.\n (region) =>\n (region.heading !== null || region.row !== null) &&\n directive.start >= region.start &&\n directive.end <= region.end,\n ),\n ) ?? null;\n\n const declaredId = (nodeDirective ? attr(nodeDirective, 'id')?.value : null) ?? frontMatterId;\n // With no directive of its own the file's identity is the provisional one,\n // computed from exactly these inputs. Settling it again would give the same\n // answer, which is why no test can tell this reuse from a second call.\n const identity = nodeDirective === null ? provisional : identityOf(declaredId, nodeDirective);\n\n // A register's sections are specifications too. The file is always the first\n // region, so a one-decision file behaves exactly as it did before. The regions\n // depend on the file's id alone, so when the directive left it unchanged the\n // provisional ones are the answer, and finding them again is the same answer.\n const regions =\n identity.id === provisional.id ? provisionalRegions : findSpecificationRegions(scanned, directives, identity.id);\n\n const status = readStatus(scanned, byKey, nodeDirective, index, file, regions);\n const pathPhase = phaseFromPath(input.path);\n // A record is a categorical statement about what the file *is*, made by\n // configuration or by an explicit directive, so it outranks a status word\n // that happened to be written inside it.\n const record = input.record === true || directives.some((directive) => directive.name === 'spec-history');\n const phase: Phase = record ? 'record' : status.phase !== 'unknown' ? status.phase : pathPhase;\n\n const title =\n (nodeDirective ? attr(nodeDirective, 'title')?.value : null) ??\n asString(byKey.get('title')) ??\n h1?.text ??\n identity.id;\n\n const document: DocumentNode = {\n id: identity.id,\n kind: 'document',\n title,\n at: at(0, Math.min(scanned.text.length, index.lineEnd(1))),\n path: input.path,\n aliases: identity.aliases,\n phase,\n history: record,\n rawStatus: status.raw,\n statusAt: status.at,\n frontMatter: toRecord(entries),\n };\n\n // Every region but the first: a heading section, or a row of a register kept\n // as a table.\n const subSpecifications = regions\n .filter((region) => region.heading !== null || region.row !== null)\n .map((region) =>\n buildRegion({\n region,\n containerId: identity.id,\n input,\n scanned,\n directives,\n index,\n file,\n pathPhase,\n record,\n inherited,\n }),\n );\n\n // The specification that owns an offset: the innermost region around it, or\n // the file when no region holds it and `regionAt` answers `null`.\n const documentAt = (offset: number): DocumentNode => {\n const region = regionAt(regions, offset);\n return subSpecifications.find((spec) => spec.region === region)?.document ?? document;\n };\n const ownerAt = (offset: number): string => documentAt(offset).id;\n\n const allItems = extractItems({ scanned, directives, ownerAt, file, index });\n\n const allReferences = extractReferences({\n scanned,\n directives,\n document,\n documentAt,\n items: allItems,\n byKey,\n status,\n claimed: regions.flatMap((region) => [...region.claimed]),\n file,\n index,\n });\n\n // Hand each region the items and references that fall inside it.\n const ownItems = allItems.filter((item) => item.document === identity.id);\n const ownReferences = allReferences.filter((reference) => belongsTo(reference, identity.id, allItems));\n const misreadKeys = misreadRelationKeys(byKey, identity.id, at);\n const anchors = anchorsOf(scanned.headings);\n\n const filled = subSpecifications.map((spec) => ({\n ...spec.extracted,\n items: allItems.filter((item) => item.document === spec.document.id),\n references: [\n // Column-declared relations first: they are typed by the header rather\n // than guessed from prose.\n ...spec.extracted.references,\n ...allReferences.filter((reference) => belongsTo(reference, spec.document.id, allItems)),\n ],\n }));\n\n return {\n document,\n items: ownItems,\n references: ownReferences,\n problems,\n misreadKeys,\n anchors,\n identity,\n scanned,\n subSpecifications: filled,\n containerId: null,\n };\n}\n\n/** True when a reference was written on a document or on one of its items. */\nfunction belongsTo(reference: ReferenceCandidate, documentId: string, items: readonly ItemNode[]): boolean {\n if (reference.from === documentId) return true;\n const owner = items.find((item) => item.id === reference.from);\n return owner?.document === documentId;\n}\n\ninterface RegionInput {\n readonly region: SpecificationRegion;\n readonly containerId: string;\n readonly input: ExtractInput;\n readonly scanned: ScannedDocument;\n readonly directives: readonly Directive[];\n readonly index: LineIndex;\n readonly file: string;\n readonly pathPhase: Phase;\n /** The whole file is a historical record, so every part of it is one too. */\n readonly record: boolean;\n /** The file's front matter, minus the keys a region must answer itself. */\n readonly inherited: Readonly<Record<string, string | readonly string[]>>;\n}\n\ninterface BuiltRegion {\n readonly region: SpecificationRegion;\n readonly document: DocumentNode;\n readonly extracted: ExtractedDocument;\n}\n\n/**\n * Turns one region into a specification.\n *\n * It produces exactly the `DocumentNode` a whole file produces, which is the\n * reason every rule, query and reporter works on registers without knowing they\n * exist. The only deliberate differences: the node is anchored at its heading\n * rather than at line one, it carries the file's front matter rather than front\n * matter of its own, and it does not claim the file's path as an alias - the\n * file already does, and two nodes answering to one path would make every link\n * to that file ambiguous.\n */\nfunction buildRegion(context: RegionInput): BuiltRegion {\n const { region, input, scanned, index, file, pathPhase, record, inherited } = context;\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n const identity = identify({\n path: input.path,\n declaredId: region.declaredId,\n declaredAliases: region.directive ? attrList(region.directive, 'aliases') : [],\n heading: region.title,\n includePathAliases: false,\n });\n\n const declaredStatus = region.directive ? attr(region.directive, 'status') : null;\n const rawStatus = declaredStatus?.value ?? region.status?.text ?? null;\n const statusAt = declaredStatus\n ? at(declaredStatus.start, declaredStatus.end)\n : region.status\n ? at(region.status.start, region.status.end)\n : null;\n const declaredPhase = phaseOf(rawStatus);\n\n const document: DocumentNode = {\n id: identity.id,\n kind: 'document',\n title: (region.directive ? attr(region.directive, 'title')?.value : null) ?? region.title ?? identity.id,\n // Anchored at its heading, or at the row when the register is a table. Every\n // region here has one or the other, so neither `?.` ever stops the chain.\n at: at(region.start, Math.min(region.end, region.heading?.end ?? region.row?.end ?? region.end)),\n path: input.path,\n aliases: identity.aliases,\n // A section of a journal is part of the journal, whatever status word it\n // wrote for itself. Being a record is a statement about the file made from\n // outside it, and it does not stop at a heading.\n phase: record ? 'record' : declaredPhase !== 'unknown' ? declaredPhase : pathPhase,\n history: record,\n rawStatus,\n statusAt,\n frontMatter: inherited,\n };\n\n const anchors = anchorsOf(scanned.headings.filter((h) => h.start >= region.start && h.start < region.end));\n\n // Relations a table declares by column, typed by the header the author wrote.\n const references: ReferenceCandidate[] = region.relations.map((relation) => ({\n kind: relation.kind,\n from: document.id,\n target: relation.target,\n origin: 'front-matter' as const,\n declaredAt: at(relation.start, relation.end),\n raw: `${relation.column}: ${relation.target}`,\n inverted: relation.inverted,\n opportunistic: false,\n }));\n\n return {\n region,\n document,\n extracted: {\n document,\n // Never read: the file's extraction replaces it once every item's owner\n // is known.\n items: [],\n references,\n problems: [],\n // The file has already reported anything misread at the top of it, and\n // there is one file however many regions it holds.\n misreadKeys: [],\n anchors,\n identity,\n scanned,\n subSpecifications: [],\n containerId: context.containerId,\n },\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Status */\n/* -------------------------------------------------------------------------- */\n\ninterface StatusReading {\n readonly raw: string | null;\n readonly at: SourceRef | null;\n readonly phase: Phase;\n}\n\n/**\n * Finds the document status.\n *\n * Looks in the places teams actually put it, in descending order of how\n * deliberate each is: a directive, a front-matter field, then the body of a\n * `## Status` section or a key-value table above the first section. A\n * repository using none of them still gets a phase from its directory layout,\n * which is handled by the caller.\n *\n * A status section inside a register's region is that region's, not the\n * file's. Read as the file's, a register whose first decision said\n * `### Status` / `Superseded by ADR-0009` was itself retired, and itself\n * superseded by ADR-0009, for something one of its decisions said.\n */\nfunction readStatus(\n scanned: ScannedDocument,\n byKey: ReadonlyMap<string, YamlEntry>,\n nodeDirective: Directive | null,\n index: LineIndex,\n file: string,\n regions: readonly SpecificationRegion[],\n): StatusReading {\n if (nodeDirective) {\n const declared = attr(nodeDirective, 'status');\n if (declared) {\n return {\n raw: declared.value,\n at: refOf(file, index, declared.start, declared.end),\n phase: phaseOf(declared.value),\n };\n }\n }\n\n for (const key of STATUS_KEYS) {\n const entry = byKey.get(key);\n if (!entry) continue;\n const raw = typeof entry.value === 'string' ? entry.value : entry.value.join(', ');\n if (raw.trim().length === 0) continue;\n return {\n raw,\n at: refOf(file, index, entry.valueStart, entry.end),\n phase: phaseOf(raw),\n };\n }\n\n const heading = scanned.headings.find((h) => isStatusHeading(h.text) && regionAt(regions, h.start) === null);\n if (heading) {\n const body = statusSectionBody(scanned, heading.line);\n if (body) {\n return {\n raw: body.text,\n at: refOf(file, index, body.start, body.end),\n phase: phaseOf(body.text),\n };\n }\n }\n\n const cell = statusTableCell(scanned);\n if (cell) {\n return {\n raw: cell.text,\n at: refOf(file, index, cell.start, cell.end),\n phase: phaseOf(cell.text),\n };\n }\n\n return { raw: null, at: null, phase: 'unknown' };\n}\n\n/** The left cells that make a two-column table's row the document's status. */\nconst STATUS_TABLE_KEYS: ReadonlySet<string> = new Set(['status', 'state']);\n\n/**\n * The status a key-value table at the top of a document gives:\n * `| Status | Accepted |`, as the right cell of the first row whose left cell\n * is a status key, the header row included.\n *\n * Read only where a document describes itself. A table under a heading below\n * the title is a legend or a register, and one with more than two columns is\n * not a list of the document's fields; neither is its status. A table\n * spec-graph reads as a register is left to its rows. Ranked with a `## Status`\n * section, after one: a document that has both is read from the section.\n */\nfunction statusTableCell(scanned: ScannedDocument): TableCell | null {\n const body = scanned.headings.find((h) => h.level >= 2)?.start ?? scanned.text.length;\n for (const table of scanned.tables) {\n // Tables come in order, and none starts on a heading's line, so `>` would\n // stop at the same table.\n if (table.start >= body) break;\n if (table.headers.length !== 2 || isRegisterTable(table)) continue;\n for (const cells of [table.headers, ...table.rows.map((row) => row.cells)]) {\n // A row always has a first cell: a line with no cell ends the table.\n const key = cells[0] as TableCell;\n const value = cells[1];\n // A row written short, or with nothing on the right, declares nothing.\n if (value === undefined || value.text.length === 0) continue;\n if (STATUS_TABLE_KEYS.has(key.text.replace(/[*_]/g, '').toLowerCase())) return value;\n }\n }\n return null;\n}\n\n/** The first non-blank line under a `## Status` heading. */\nfunction statusSectionBody(\n scanned: ScannedDocument,\n headingLine: number,\n): { text: string; start: number; end: number } | null {\n for (const line of scanned.lines) {\n if (line.line <= headingLine) continue;\n if (line.blank || isOnlyComment(scanned, line)) continue;\n if (!isMarkdownLine(line)) return null;\n // A heading immediately after means the section is empty - a setext one\n // too, whose text line does not start with `#` and read as the status.\n if (opensHeading(scanned, line.line)) return null;\n const trimmed = line.content.trim();\n const offset = line.contentStart + line.content.indexOf(trimmed);\n // Bullet lists under Status are a status history; take the first entry.\n const cleaned = trimmed.replace(/^[-*+]\\s+/, '');\n const start = offset + (trimmed.length - cleaned.length);\n return { text: cleaned, start, end: start + cleaned.length };\n }\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Items */\n/* -------------------------------------------------------------------------- */\n\ninterface ItemContext {\n readonly scanned: ScannedDocument;\n readonly directives: readonly Directive[];\n /** The specification that owns an offset, which in a register is a section. */\n readonly ownerAt: (offset: number) => string;\n readonly file: string;\n readonly index: LineIndex;\n}\n\nfunction extractItems(context: ItemContext): ItemNode[] {\n const { scanned, directives, ownerAt, file, index } = context;\n const out: ItemNode[] = [];\n const ordinals = new Map<string, number>();\n const bound = bindItemDirectives(scanned, directives);\n\n for (const item of scanned.listItems) {\n const section = sectionPathAt(scanned, item.start);\n const inObligationSection = section.some((heading) => OBLIGATION_SECTIONS.has(normaliseHeading(heading)));\n const directive = bound.get(item) ?? null;\n\n if (!isObligation(item, inObligationSection, directive)) continue;\n\n const documentId = ownerAt(item.start);\n const slug = section.length > 0 ? slugify(section[section.length - 1] as string) : 'item';\n // Ordinals count within a specification, so two decisions in one register\n // each get their own `#open-questions.1` rather than sharing a sequence.\n const key = `${documentId}#${slug}`;\n const ordinal = (ordinals.get(key) ?? 0) + 1;\n ordinals.set(key, ordinal);\n\n const declaredId = directive ? attr(directive, 'id')?.value : null;\n const id = `${documentId}#${declaredId ?? `${slug}.${ordinal}`}`;\n\n const state = resolveItemState({\n file,\n index,\n item,\n section,\n directive,\n inObligationSection,\n });\n\n out.push({\n id,\n kind: 'item',\n title: (directive ? attr(directive, 'title')?.value : null) ?? summarise(item.firstLine),\n at: refOf(file, index, item.start, item.end),\n declared: declaredId !== null && declaredId !== undefined,\n document: documentId,\n section,\n text: summarise(item.firstLine),\n body: item.body,\n disposition: state.disposition,\n openness: state.openness,\n evidence: state.evidence,\n conflicts: state.conflicts,\n });\n }\n\n return out;\n}\n\n/**\n * Decides whether a bullet is an obligation.\n *\n * A checkbox or an explicit directive always makes one. Otherwise only\n * top-level bullets under a heading like \"Open Questions\" count: promoting\n * every bullet in a specification would bury the real obligations under the\n * document's own prose.\n */\nfunction isObligation(item: ListItem, inObligationSection: boolean, directive: Directive | null): boolean {\n if (directive !== null) return true;\n if (item.checkbox !== null) return true;\n return inObligationSection && item.depth === 0;\n}\n\n/** The heading path enclosing an offset, outermost first. */\nfunction sectionPathAt(scanned: ScannedDocument, offset: number): string[] {\n const path: { level: number; text: string }[] = [];\n for (const heading of scanned.headings) {\n // A heading opening exactly at the offset would be a reference or an item\n // starting on a `#` or on the first word of a setext heading - and a heading\n // that begins with a reference is no section name either way.\n if (heading.start > offset) break;\n while (path.length > 0 && (path[path.length - 1] as { level: number }).level >= heading.level) path.pop();\n path.push({ level: heading.level, text: heading.text });\n }\n return path.map((entry) => entry.text);\n}\n\n/**\n * Memoised because it is called for every heading above every reference and\n * every item, and a corpus has only a handful of distinct headings - `Context`,\n * `Decision`, `Open Questions`, `See also` - repeated thousands of times.\n *\n * The cache changes how fast an answer arrives and never the answer, so no test\n * can see whether it is consulted, filled or bounded.\n */\nconst headingCache = new Map<string, string>();\n\nfunction normaliseHeading(text: string): string {\n const cached = headingCache.get(text);\n if (cached !== undefined) return cached;\n const normalised = text\n .toLowerCase()\n .replace(/[`*_~]/g, '')\n .replace(/[^\\p{L}\\p{N}\\s-]/gu, '')\n .replace(/\\s+/g, ' ')\n .trim();\n // Bounded so a pathological corpus of unique headings cannot grow it forever.\n if (headingCache.size < 4096) headingCache.set(text, normalised);\n return normalised;\n}\n\n/**\n * One-line form of an item for reports.\n *\n * Link syntax is flattened to its label. A finding that quotes the obligation\n * back at the reader should read like the sentence they wrote, not like the\n * Markdown source of it.\n */\nfunction summarise(text: string): string {\n const flat = text\n // An image first, so that a badge wrapped in a link, `[![icon](i.png)](x)`,\n // leaves `[icon](x)` for the link's pattern rather than a stray `![icon](x)`.\n .replace(/!\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n // `[[target|display]]` keeps the display half: that is the text a reader\n // of the rendered document actually sees.\n .replace(/\\[\\[(?:[^\\]|]*\\|)?([^\\]]*)\\]\\]/g, '$1')\n .replace(/\\s+/g, ' ')\n .trim();\n return flat.length <= 120 ? flat : `${flat.slice(0, 117)}...`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* References */\n/* -------------------------------------------------------------------------- */\n\ninterface ReferenceContext {\n readonly scanned: ScannedDocument;\n readonly directives: readonly Directive[];\n readonly document: DocumentNode;\n /** The specification that owns an offset, for a reference outside any item. */\n readonly documentAt: (offset: number) => DocumentNode;\n readonly items: readonly ItemNode[];\n readonly byKey: ReadonlyMap<string, YamlEntry>;\n readonly status: StatusReading;\n /** Cell ranges already typed by a table column header. */\n readonly claimed: readonly { start: number; end: number }[];\n readonly file: string;\n readonly index: LineIndex;\n}\n\n/**\n * True when an offset falls in a cell a column header already accounted for.\n *\n * Whether the end is in or out decides nothing: what sits there is the cell's\n * closing pipe or the space before it, and no reference starts on either.\n */\nfunction isClaimed(claimed: readonly { start: number; end: number }[], offset: number): boolean {\n return claimed.some((range) => offset >= range.start && offset < range.end);\n}\n\nfunction extractReferences(context: ReferenceContext): ReferenceCandidate[] {\n const { scanned, directives, document, documentAt, items, byKey, status, claimed, file, index } = context;\n // This list and the one `withoutOverlaps` builds from it are only ever read\n // through `belongsTo`, which passes nothing that was not written on a\n // document or one of its items: a stray entry in either would reach no one.\n const out: ReferenceCandidate[] = [];\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n // Front matter, walked in the order it was written rather than in the order\n // the vocabulary happens to be listed: a key the table does not know still has\n // to be looked at, and only the document knows which those are.\n for (const [key, entry] of byKey) {\n const relation = RELATION_INDEX.get(foldRelationKey(key));\n if (!relation) continue;\n for (const value of valuesOf(entry)) {\n const target = cleanTarget(value);\n if (target.length === 0) continue;\n out.push({\n kind: relation.kind,\n from: document.id,\n target,\n origin: 'front-matter',\n declaredAt: at(entry.valueStart, entry.end),\n raw: `${key}: ${value}`,\n inverted: relation.inverted,\n opportunistic: false,\n });\n }\n }\n\n // `status: Superseded by ADR-0009` is the most common supersession record of\n // all, and it never appears as a field of its own. A reading carries its text\n // and its place together or neither, so either test alone would do.\n if (status.raw && status.at) {\n for (const target of supersessionTargetsIn(status.raw)) {\n const cleaned = cleanTarget(target);\n if (cleaned.length === 0) continue;\n out.push({\n kind: 'supersedes',\n from: document.id,\n target: cleaned,\n origin: 'front-matter',\n declaredAt: status.at,\n raw: status.raw,\n inverted: true,\n opportunistic: true,\n });\n }\n }\n\n // Explicit edge directives.\n for (const directive of directives) {\n if (directive.name !== 'spec-edge') continue;\n const kind = attr(directive, 'kind')?.value as EdgeKind | undefined;\n const to = attr(directive, 'to');\n const from = attr(directive, 'from');\n if (!kind) continue;\n const owner = ownerOf(items, directive.start) ?? documentAt(directive.start).id;\n if (to) {\n out.push({\n kind,\n from: owner,\n target: to.value,\n origin: 'directive',\n declaredAt: at(to.start, to.end),\n raw: `@spec-edge kind=\"${kind}\" to=\"${to.value}\"`,\n inverted: false,\n opportunistic: false,\n });\n }\n if (from) {\n out.push({\n kind,\n from: owner,\n target: from.value,\n origin: 'directive',\n declaredAt: at(from.start, from.end),\n raw: `@spec-edge kind=\"${kind}\" from=\"${from.value}\"`,\n inverted: true,\n opportunistic: false,\n });\n }\n }\n\n // Prose links. A cell whose meaning a column header already gave is skipped,\n // so `| ADR-0002 | ... | [ADR-0001](0001.md) |` yields one typed edge rather\n // than a typed edge and a neutral citation beside it.\n const linked = new Set<string>();\n const links = referenceLinks(scanned);\n for (const link of links) {\n if (link.form === 'definition') continue;\n if (isClaimed(claimed, link.start)) continue;\n const target = cleanTarget(link.target);\n if (target.length === 0) continue;\n if (isExternal(target)) continue;\n\n const owner = ownerOf(items, link.start) ?? documentAt(link.start).id;\n const section = sectionPathAt(scanned, link.start);\n const classified = classifyReference(scanned.masks.structure, link.start, link.end, section);\n\n linked.add(normaliseRef(stripAnchor(target)));\n out.push({\n kind: classified.kind,\n from: owner,\n target,\n origin: 'link',\n declaredAt: at(link.targetStart, link.targetEnd),\n raw: renderLink(link),\n inverted: classified.inverted,\n opportunistic: false,\n });\n }\n\n // Bare identifiers in prose. Everything already covered by a link is skipped\n // so a citation written as `[ADR-7](0007.md)` is not counted twice.\n for (const bare of findBareReferences(scanned, links)) {\n const key = normaliseRef(bare.text);\n if (linked.has(key)) continue;\n if (isClaimed(claimed, bare.start)) continue;\n const owner = ownerOf(items, bare.start) ?? documentAt(bare.start).id;\n const section = sectionPathAt(scanned, bare.start);\n const classified = classifyReference(scanned.masks.structure, bare.start, bare.end, section);\n out.push({\n kind: classified.kind,\n from: owner,\n target: bare.text,\n origin: 'text',\n declaredAt: at(bare.start, bare.end),\n raw: bare.text,\n inverted: classified.inverted,\n opportunistic: true,\n });\n }\n\n return withoutOverlaps(out);\n}\n\n/**\n * Collapses candidates that describe the same written citation.\n *\n * `Superseded by ADR-0009` in a status section is read twice: the status\n * reader reports the whole line, and prose scanning reports the identifier\n * inside it. One written citation is one reference - so when the target\n * resolves it must not become two edges, and when it does not it must not\n * become two findings on one line a reader can only fix once.\n *\n * The narrower span wins, because it points at the text that has to change.\n *\n * Only overlapping spans collapse. Two sentences citing the same missing\n * document are two citations, and silently reporting one of them would leave\n * the other to be discovered on the next run.\n */\nfunction withoutOverlaps(candidates: readonly ReferenceCandidate[]): ReferenceCandidate[] {\n const out: ReferenceCandidate[] = [];\n for (const candidate of candidates) {\n // Today the only readings that can overlap are a status line and the prose\n // inside it, by one owner, and where they disagree they disagree on kind and\n // direction together. So the kind, owner and direction tests below cannot\n // be told apart one by one; each is here for a reader that differs in one.\n const index = out.findIndex(\n (other) =>\n other.kind === candidate.kind &&\n other.from === candidate.from &&\n other.inverted === candidate.inverted &&\n normaliseRef(other.target) === normaliseRef(candidate.target) &&\n overlapping(other.declaredAt, candidate.declaredAt),\n );\n if (index === -1) {\n out.push(candidate);\n continue;\n }\n const held = out[index] as ReferenceCandidate;\n // The status reader runs before prose scanning, so today the wider span is\n // always the one already held and this comparison always replaces it. It is\n // written as a comparison rather than an unconditional swap because which\n // reader runs first is not a property worth depending on, and a mutant that\n // makes it unconditional is equivalent only by that accident. Two of the\n // same width that match are one value written twice in one list, alike in\n // everything, so which of them is kept cannot matter.\n if (width(candidate.declaredAt) < width(held.declaredAt)) out[index] = candidate;\n }\n return out;\n}\n\nconst width = (ref: SourceRef): number => ref.span.end.offset - ref.span.start.offset;\n\n/**\n * Whether two spans cover any of the same text.\n *\n * Offsets alone, with no file comparison: every candidate here was built from\n * one scan of one file, so there is no second file for them to be offsets into.\n * Spans that only touch never occur between two readings of one target, so\n * whether touching counts as overlapping decides nothing.\n */\nfunction overlapping(a: SourceRef, b: SourceRef): boolean {\n return a.span.start.offset < b.span.end.offset && b.span.start.offset < a.span.end.offset;\n}\n\n/**\n * The item whose block contains an offset, if any.\n *\n * An item's span runs from its indentation or list marker to the line break\n * that ends it, and no reference or directive starts on either, so both bounds\n * could be closed or open alike. Items arrive in document order, where a nested\n * item follows the one it nests in and never shares its start: the last item\n * that contains the offset is the innermost, which the comparison below says\n * rather than relies on.\n */\nfunction ownerOf(items: readonly ItemNode[], offset: number): string | null {\n let best: ItemNode | null = null;\n for (const item of items) {\n const span = item.at.span;\n if (offset < span.start.offset || offset >= span.end.offset) continue;\n if (best === null || span.start.offset > best.at.span.start.offset) best = item;\n }\n return best?.id ?? null;\n}\n\nexport interface Classification {\n readonly kind: EdgeKind;\n readonly inverted: boolean;\n}\n\n/**\n * Decides what a reference means from the words around it.\n *\n * The nearest governing phrase within {@link VERB_WINDOW} characters wins, and\n * the search never crosses a sentence boundary. With nothing to go on, a\n * reference under a \"See also\" heading is bookkeeping and everything else is a\n * neutral citation.\n */\nexport function classifyReference(\n text: string,\n start: number,\n end: number,\n section: readonly string[],\n): Classification {\n const before = sentenceBefore(text, start);\n\n // Left to right, so the last match within the window is the nearest one - and\n // the nearest governing phrase is the one that governs. `matchAll`, not a\n // loop over `exec`: an empty match leaves `lastIndex` where it began, and\n // `exec` finds it there again for ever, where `matchAll` steps past it. No\n // phrase is empty, so the pattern never matches empty; a phrase emptied by\n // mistake then fails the tests rather than hanging them.\n let best: Classification | null = null;\n for (const m of before.matchAll(VERB_PATTERN)) {\n const phrase = m[0];\n const end = m.index + phrase.length;\n const distance = before.length - end;\n if (distance > VERB_WINDOW) continue;\n // What sits between the phrase and the reference has to be connective. A\n // negation in there reverses the claim the phrase would otherwise make.\n if (NEGATION.test(before.slice(end))) continue;\n // Always found: the pattern was compiled from this table's own keys, and a\n // lower-cased search matches them only as written. The check is for types.\n const rule = VERB_LOOKUP.get(phrase);\n if (rule) best = rule;\n }\n\n if (best) return best;\n\n // \"[ADR-0009] supersedes this decision\": the reference is the subject, so the\n // relation runs the other way.\n const after = sentenceAfter(text, end);\n for (const rule of VERB_RULES) {\n if (rule.inverted) continue;\n for (const phrase of rule.phrases) {\n if (!after.startsWith(phrase)) continue;\n if (rule.kind === 'assumes' || rule.kind === 'depends-on') continue;\n return { kind: rule.kind, inverted: true };\n }\n }\n\n // Any enclosing heading will do: a link under `### Notes` inside `## See also`\n // is bookkeeping still.\n for (const heading of section) {\n if (WEAK_SECTIONS.has(normaliseHeading(heading))) return { kind: 'relates-to', inverted: false };\n }\n\n return { kind: 'references', inverted: false };\n}\n\n/** A sentence end, a blank line, or the start of a new block-level item. */\n/**\n * A table cell edge ends a statement too.\n *\n * The pipe matters more than it looks. A table row is a list of independent\n * fields, and without it the look-behind window reaches back across the row\n * boundary into the previous row's prose. An index of archived documents whose\n * last column ended \"...before assuming the drift was fixed\" turned every\n * following row's link into an `assumes` edge, and so turned every archived\n * document it listed into a stale premise.\n *\n * A sentence written in Chinese ends at `。?!;`, with a space after it or\n * none, since Chinese writes none. A stop only ends a statement sooner, so it\n * reads fewer relations and never more: without it,\n * `Deferred to later。另見 ADR-0002` handed the question to ADR-0002 from the\n * sentence before.\n */\nconst STATEMENT_BREAK = /[.?!;]\\s|[。?!;]|\\n\\s*\\n|\\n\\s*[-*+>#]|\\|/g;\n\n/**\n * Lower-cased, whitespace-collapsed text back to the start of the statement.\n *\n * The search stops at the last boundary: a governing phrase in the *previous*\n * sentence does not govern this reference. \"We deferred that to ADR-3. See also\n * [ADR-9].\" must not read as a delegation to ADR-9.\n */\nfunction sentenceBefore(text: string, start: number): string {\n const window = text.slice(Math.max(0, start - 160), start);\n let cut = 0;\n for (const m of window.matchAll(STATEMENT_BREAK)) cut = m.index + m[0].length;\n return window\n .slice(cut)\n .toLowerCase()\n .replace(/[`*_~\"'()\\[\\],]/g, ' ')\n .replace(/\\s+/g, ' ');\n}\n\n/**\n * The statement after a reference, to the first stop, the stops of a sentence\n * written in Chinese included.\n *\n * Only its start is read. A line break matters as a stop, since the trim\n * below would otherwise bring the next line's phrase to the start. A Chinese\n * stop is never trimmed, so a phrase after one cannot start the text either\n * way, and the mutants that drop one are equivalent: it is here so the\n * statement is the one `sentenceBefore` reads.\n */\nfunction sentenceAfter(text: string, end: number): string {\n const window = text.slice(end, Math.min(text.length, end + 80));\n const stop = /[.?!;\\n|。?!;]/.exec(window);\n const cut = stop ? window.slice(0, stop.index) : window;\n return cut.toLowerCase().replace(/[`*_~\"'()\\[\\],]/g, ' ').replace(/\\s+/g, ' ').trim();\n}\n\ninterface BareReference {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\n/**\n * Finds identifiers written as plain prose, such as \"as decided in ADR-0007\".\n *\n * Link constructs are blanked first. Without that, `[ADR-7](https://x/adr-7)`\n * would yield three references to the same thing - one real and two harvested\n * out of a URL - which is precisely the mis-match that makes hand-rolled regex\n * checks untrustworthy. Images are not blanked, since they are not references:\n * an identifier in one's text is prose, as it always was here.\n */\nfunction findBareReferences(scanned: ScannedDocument, links: readonly Link[]): BareReference[] {\n // Slice-based for the same reason as the scanner's masking: this runs over\n // every document, and a per-character array is the wrong shape for the job.\n const source = scanned.masks.structure;\n let text = '';\n let cursor = 0;\n for (const link of links) {\n const start = Math.max(link.start, cursor);\n const end = Math.min(link.end, source.length);\n // Links from one scan come in order and never nest, so this skips nothing\n // today. It keeps a scanner that did nest them from copying text twice.\n if (end <= start) continue;\n text += source.slice(cursor, start);\n text += source.slice(start, end).replace(/[^\\n\\r]/g, ' ');\n cursor = end;\n }\n text += source.slice(cursor);\n\n const out: BareReference[] = [];\n for (const m of text.matchAll(BARE_REF)) {\n const written = m[0];\n // The family as resolution will read it, which takes the shortest prefix\n // the number allows: `base64` is `base` and 64. Read off this pattern's\n // greedy prefix it was `base6` and 4, and `ES2015`, `ARM64` and `Win32`\n // walked past the list below as families of their own. Every match is a\n // prefixed identifier by construction, so the parse cannot fail.\n const family = (parsePrefixedRef(written) as { family: string }).family.toLowerCase();\n if (NOT_A_FAMILY.has(family)) continue;\n if (family.length < 2) continue;\n const start = m.index;\n // A token glued to a path separator or an extension is not a citation. At\n // either end of the text the stand-in need only be neither `/` nor `.`.\n const before = text[start - 1] ?? ' ';\n const after = text[start + written.length] ?? ' ';\n if (before === '/' || before === '.' || after === '/') continue;\n out.push({ text: written, start, end: start + written.length });\n }\n return out;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction firstValue(byKey: ReadonlyMap<string, YamlEntry>, keys: readonly string[]): string | null {\n for (const key of keys) {\n // A key that is missing reads as null, the same as a blank one.\n const value = asString(byKey.get(key));\n if (value !== null && value.length > 0) return value;\n }\n return null;\n}\n\nfunction asString(entry: YamlEntry | undefined): string | null {\n if (!entry) return null;\n if (typeof entry.value === 'string') return entry.value.trim().length > 0 ? entry.value.trim() : null;\n return entry.value.length > 0 ? (entry.value[0] as string) : null;\n}\n\n/** Strips Markdown decoration a target may still be wearing. */\nfunction cleanTarget(value: string): string {\n return value\n .trim()\n .replace(/^[`'\"<(\\[]+/, '')\n .replace(/[`'\">)\\]]+$/, '')\n .replace(/[.,;]+$/, '')\n .trim();\n}\n\nfunction stripAnchor(target: string): string {\n const hash = target.indexOf('#');\n return hash <= 0 ? target : target.slice(0, hash);\n}\n\n/**\n * A link's text for an edge's `raw`.\n *\n * An autolink never reaches here: spec-core reads one only when it carries a\n * scheme, and a link with a scheme is external and was dropped before this. A\n * reference or shortcut link always has a label, so the `''` is for the type.\n */\nfunction renderLink(link: Link): string {\n switch (link.form) {\n case 'wiki':\n return `[[${link.target}]]`;\n case 'reference':\n case 'shortcut':\n return `[${link.text}][${link.label ?? ''}]`;\n default:\n return `[${link.text}](${link.target})`;\n }\n}\n\n/** Exposed for tests and for callers that classify their own sections. */\nexport { OBLIGATION_SECTIONS, sectionPathAt, WEAK_SECTIONS };\n"]}
package/dist/sections.js CHANGED
@@ -280,12 +280,11 @@ function splitTargets(cell) {
280
280
  // Links are taken out whole rather than flattened with everything else: a
281
281
  // path would otherwise be cut in half by its own slash, and its underscores
282
282
  // stripped as emphasis.
283
- // A fresh matcher per cell. `prose` calls `flatten`, which drives the shared
284
- // pattern; one /g regex advanced from inside its own scan resets its cursor
285
- // and never terminates.
286
- const links = new RegExp(MARKDOWN_LINK.source, 'g');
283
+ // `matchAll` scans a copy of the pattern. `prose` calls `flatten`, which
284
+ // drives the shared one, and one /g regex advanced from inside its own scan
285
+ // resets its cursor and never terminates.
287
286
  let last = 0;
288
- for (let match = links.exec(cell.text); match !== null; match = links.exec(cell.text)) {
287
+ for (const match of cell.text.matchAll(MARKDOWN_LINK)) {
289
288
  prose(cell.text.slice(last, match.index));
290
289
  // Both groups always take part in a match, so the `?? ''` below and in the
291
290
  // label are for the type.
@@ -1 +1 @@
1
- {"version":3,"file":"sections.js","sourceRoot":"","sources":["../src/sections.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Specification regions: the part of a file that one specification occupies.\n *\n * `spec-graph` began by assuming one specification per file, because that is\n * how MADR, KEPs and Rust RFCs are laid out. Plenty of organisations do not\n * work that way. A register, a whitepaper or a living architecture document\n * holds dozens of decisions in one file, each with its own identifier, its own\n * status and its own dependencies - and to an engine that binds a document to a\n * file, every one of them is invisible.\n *\n * The fix is small once stated: **a specification is a region of a file, not a\n * file.** A file yields at least one region - itself - and may yield more.\n * Everything downstream is unchanged, because a region produces exactly the\n * same `DocumentNode` a whole file produced.\n *\n * What this module decides is where those regions begin and end, and it is\n * deliberately hard to convince. A heading has to carry an identifier *and* the\n * section has to declare a status before it counts. One signal is not enough:\n * `## Q3 2026 Roadmap` parses as family `Q`, number 3, and `## v1.2.0` in a\n * changelog parses as family `v`, number 1. Neither is a specification, and\n * neither declares a status.\n */\n\nimport { attr, type Directive } from './directives.js';\nimport { HAS_LETTER_OR_DIGIT, isExternal, parsePrefixedRef } from './identity.js';\nimport { isStatusHeading } from './lifecycle.js';\nimport {\n isMarkdownLine,\n isOnlyComment,\n type Heading,\n type Range,\n type ScannedDocument,\n type Table,\n type TableCell,\n type TableRow,\n} from './markdown.js';\nimport type { EdgeKind } from './types.js';\n\n/** A status as written, and where it was written. */\nexport interface RegionStatus {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\n/** A relation read from a table column rather than from prose. */\nexport interface TableRelation {\n readonly kind: EdgeKind;\n readonly inverted: boolean;\n readonly target: string;\n readonly start: number;\n readonly end: number;\n /** The column header that gave it its meaning, for the diagnostic. */\n readonly column: string;\n}\n\nexport interface SpecificationRegion {\n /** The heading that opens the region, or `null` for the file or a table row. */\n readonly heading: Heading | null;\n /** The table row that is the region, when it is one. */\n readonly row: TableRow | null;\n /** Offset the region starts at. */\n readonly start: number;\n /** Offset just past the region. */\n readonly end: number;\n /** Identifier read from the heading or the identifier column. */\n readonly declaredId: string | null;\n readonly title: string | null;\n readonly status: RegionStatus | null;\n /** A `@spec-node` directive inside the region, when there is one. */\n readonly directive: Directive | null;\n /** Relations declared by column, empty for a heading region. */\n readonly relations: readonly TableRelation[];\n /**\n * Cells whose content is already accounted for as a typed relation.\n *\n * Prose scanning skips these, so a link in a `Depends on` column produces one\n * typed edge rather than a typed edge and a neutral citation beside it.\n */\n readonly claimed: readonly Range[];\n}\n\n/** Column headers that name the row's identifier. */\nconst ID_COLUMNS = /^(?:id|ids|ref|reference|key|no|number|#|adr|rfc|kep|oi|decision|spec|specification)$/;\n\n/** Column headers that name the row's status. */\nconst STATUS_COLUMNS = /^(?:status|state|stage|lifecycle|phase)$/;\n\n/** Column headers that name the row's title. */\nconst TITLE_COLUMNS = /^(?:title|name|summary|description|subject|decision|topic)$/;\n\n/**\n * Column headers that declare a relation.\n *\n * Written the way a header is written - \"Depends on\", \"Superseded by\" - rather\n * than the way a front-matter key is, because that is what an author types at\n * the top of a column.\n */\nconst RELATION_COLUMNS: Readonly<Record<string, { kind: EdgeKind; inverted: boolean }>> = {\n 'depends on': { kind: 'depends-on', inverted: false },\n 'depends-on': { kind: 'depends-on', inverted: false },\n dependencies: { kind: 'depends-on', inverted: false },\n requires: { kind: 'depends-on', inverted: false },\n supersedes: { kind: 'supersedes', inverted: false },\n replaces: { kind: 'supersedes', inverted: false },\n 'superseded by': { kind: 'supersedes', inverted: true },\n 'replaced by': { kind: 'supersedes', inverted: true },\n 'blocked by': { kind: 'blocked-by', inverted: false },\n 'blocked on': { kind: 'blocked-by', inverted: false },\n blocks: { kind: 'blocked-by', inverted: true },\n amends: { kind: 'amends', inverted: false },\n extends: { kind: 'amends', inverted: false },\n assumes: { kind: 'assumes', inverted: false },\n 'delegates to': { kind: 'delegates-to', inverted: false },\n 'delegated to': { kind: 'delegates-to', inverted: false },\n 'tracked in': { kind: 'delegates-to', inverted: false },\n related: { kind: 'relates-to', inverted: false },\n 'related to': { kind: 'relates-to', inverted: false },\n 'see also': { kind: 'relates-to', inverted: false },\n references: { kind: 'references', inverted: false },\n};\n\n/** Cell values that mean \"nothing here\". */\nconst MARKDOWN_LINK = /!?\\[([^\\]]*)\\]\\(([^)]*)\\)/g;\nconst EMPTY_CELL = /^(?:-+|—|–|n\\/?a|none|nil|tbd|\\.|_+)$/i;\n\n/** `## ADR-0007: Sharding` - an identifier at the very start of a heading. */\nconst HEADING_ID = /^\\s*([A-Za-z]{1,15}[\\s._-]?\\d{1,6})\\b/;\n\n/** `**Status:** Accepted`, `Status: Accepted`, `*Status* : Accepted`. */\nconst INLINE_STATUS = /^[ \\t>]*[*_]{0,2}\\s*status\\s*[*_]{0,2}\\s*:\\s*(.+?)\\s*$/im;\n\n/**\n * Finds every specification in a file.\n *\n * The first entry is always the file itself, so a caller that ignores the rest\n * behaves exactly as it did before regions existed.\n */\nexport function findSpecificationRegions(\n scanned: ScannedDocument,\n directives: readonly Directive[],\n /** The file's own identifier, so its title heading is not read as a sub-region. */\n fileId: string,\n): SpecificationRegion[] {\n // The file's own relations come from its front matter and prose, never from\n // here, and it claims no cell: nothing reads either list off this region.\n const whole: SpecificationRegion = {\n heading: null,\n row: null,\n start: scanned.bodyStart,\n end: scanned.text.length,\n declaredId: null,\n title: null,\n status: null,\n directive: null,\n relations: [],\n claimed: [],\n };\n\n const regions: SpecificationRegion[] = [];\n const folded = fold(fileId);\n const fileRef = parsePrefixedRef(fileId);\n\n for (let i = 0; i < scanned.headings.length; i += 1) {\n const heading = scanned.headings[i] as Heading;\n const declaredId = HEADING_ID.exec(heading.text)?.[1];\n if (declaredId === undefined) continue;\n // The file's own title heading names the file, not a region inside it.\n if (fold(declaredId) === folded) continue;\n // Padding is not part of an identity anywhere else - `ADR-40`, `ADR-040`\n // and `ADR-0040` all resolve to one document - so a heading that spells the\n // number differently from the file name is still that file's own title.\n // Comparing the text alone made `# ADR-040` inside `0040-enforce.md` a\n // region within the file it names: one decision, two nodes, and a citation\n // arriving at whichever spelling it happened to use.\n // `HEADING_ID` captures only what `PREFIXED_ID` parses, so `ref` is never\n // null here; the check is for the type.\n const ref = parsePrefixedRef(declaredId);\n if (ref !== null && fileRef !== null && ref.family === fileRef.family && ref.number === fileRef.number) continue;\n\n const end = regionEnd(scanned, i);\n const directive = directiveIn(directives, heading.end, end);\n const status = readRegionStatus(scanned, heading.end, end);\n\n // Two independent signals are required. An identifier alone matches\n // `## Q3 2026 Roadmap` and `## v1.2.0`; a status alone matches every\n // ordinary `## Status` section in a normal ADR.\n if (status === null && directive === null) continue;\n\n // A directive's id wins, but only if it is a name. One that is not - the\n // lone backslash `id=\\\"ADR-9\\\"` parses to, written inside a string - would\n // be discarded when the region is identified, and a region with nothing\n // to go by falls back to the file's own name: the file then contained\n // itself, and the section vanished. The heading's id is the one to keep.\n const directiveId = directive ? attr(directive, 'id')?.value : undefined;\n\n regions.push({\n heading,\n row: null,\n start: heading.start,\n end,\n declaredId: directiveId !== undefined && HAS_LETTER_OR_DIGIT.test(directiveId) ? directiveId : declaredId,\n title: heading.text,\n status,\n directive,\n relations: [],\n // Prose inside a section is prose: a heading region claims no cell.\n claimed: [],\n });\n }\n\n return [whole, ...regions, ...findTableRegions(scanned)];\n}\n\n/* -------------------------------------------------------------------------- */\n/* Registers kept as tables */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Reads a table whose columns describe specifications.\n *\n * A table qualifies when it has an identifier column *and* either a status\n * column or at least one relation column. Two signals again, for the same\n * reason: a table of identifiers and prose is a citation list, and promoting\n * every row of it to a specification would invent a register nobody wrote.\n */\nexport function findTableRegions(scanned: ScannedDocument): SpecificationRegion[] {\n const out: SpecificationRegion[] = [];\n\n for (const table of scanned.tables) {\n const schema = readSchema(table);\n if (schema === null) continue;\n\n for (const row of table.rows) {\n const idCell = row.cells[schema.id];\n if (!idCell) continue;\n const id = flatten(idCell.text);\n // A row is named by its id cell or not at all. An empty one, a\n // placeholder, or punctuation alone - `?` for a row nobody has numbered\n // yet - names nothing, and a region with no name fell back to the file's:\n // the register then contained itself, and the row vanished.\n if (!HAS_LETTER_OR_DIGIT.test(id) || EMPTY_CELL.test(id)) continue;\n\n // `row.cells[null]` is undefined too, so the null checks on the optional\n // columns are for the type; and `statusText` is read only beside a cell.\n const statusCell = schema.status === null ? undefined : row.cells[schema.status];\n const statusText = statusCell ? flatten(statusCell.text) : '';\n const status: RegionStatus | null =\n statusCell && statusText.length > 0 && !EMPTY_CELL.test(statusText)\n ? { text: statusText, start: statusCell.start, end: statusCell.end }\n : null;\n\n const titleCell = schema.title === null ? undefined : row.cells[schema.title];\n const title = titleCell ? flatten(titleCell.text) : null;\n\n const relations: TableRelation[] = [];\n // The status cell is left to prose, as a status line under a heading is:\n // `Superseded by ADR-0002` there names the row's successor, and claimed\n // it named nothing at all.\n const claimed: Range[] = [{ start: idCell.start, end: idCell.end }];\n\n for (const [column, relation] of schema.relations) {\n const cell = row.cells[column];\n if (!cell) continue;\n claimed.push({ start: cell.start, end: cell.end });\n for (const target of splitTargets(cell)) {\n relations.push({\n kind: relation.kind,\n inverted: relation.inverted,\n target: target.text,\n start: target.start,\n end: target.end,\n column: (table.headers[column] as TableCell).text,\n });\n }\n }\n\n out.push({\n heading: null,\n row,\n start: row.start,\n end: row.end,\n declaredId: id,\n title: title !== null && title.length > 0 ? title : null,\n status,\n directive: null,\n relations,\n claimed,\n });\n }\n }\n\n return out;\n}\n\n/**\n * Whether spec-graph reads a table as a register: an identifier column, and a\n * status column or a relation column beside it. Such a table's status column\n * describes its rows, never the document holding it.\n */\nexport function isRegisterTable(table: Table): boolean {\n return readSchema(table) !== null;\n}\n\ninterface TableSchema {\n readonly id: number;\n readonly status: number | null;\n readonly title: number | null;\n readonly relations: readonly (readonly [number, { kind: EdgeKind; inverted: boolean }])[];\n}\n\nfunction readSchema(table: Table): TableSchema | null {\n let id: number | null = null;\n let status: number | null = null;\n let title: number | null = null;\n const relations: [number, { kind: EdgeKind; inverted: boolean }][] = [];\n\n table.headers.forEach((header, column) => {\n const name = normaliseHeader(header.text);\n if (id === null && ID_COLUMNS.test(name)) {\n id = column;\n return;\n }\n if (status === null && STATUS_COLUMNS.test(name)) {\n status = column;\n return;\n }\n const relation = RELATION_COLUMNS[name];\n if (relation) {\n relations.push([column, relation]);\n return;\n }\n if (title === null && TITLE_COLUMNS.test(name)) title = column;\n });\n\n // Without an id column every row would be skipped for want of an id cell;\n // this says so before reading any of them.\n if (id === null) return null;\n if (status === null && relations.length === 0) return null;\n return { id, status, title, relations };\n}\n\nfunction normaliseHeader(text: string): string {\n return flatten(text)\n .toLowerCase()\n .replace(/[^a-z0-9/#\\s-]/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/** Splits a cell into the identifiers it lists, keeping each one's offset. */\nfunction splitTargets(cell: TableCell): { text: string; start: number; end: number }[] {\n const out: { text: string; start: number; end: number }[] = [];\n // Every target is reported at the cell's span. A cell is short, and an offset\n // recovered back through a flattening is an offset that can drift.\n const push = (raw: string): void => {\n const target = raw.trim();\n if (target.length === 0 || EMPTY_CELL.test(target)) return;\n out.push({ text: target, start: cell.start, end: cell.end });\n };\n const prose = (segment: string): void => {\n for (const piece of flatten(segment).split(/\\s*(?:[,;]|\\band\\b)\\s*/i)) push(piece);\n };\n\n // Links are taken out whole rather than flattened with everything else: a\n // path would otherwise be cut in half by its own slash, and its underscores\n // stripped as emphasis.\n // A fresh matcher per cell. `prose` calls `flatten`, which drives the shared\n // pattern; one /g regex advanced from inside its own scan resets its cursor\n // and never terminates.\n const links = new RegExp(MARKDOWN_LINK.source, 'g');\n let last = 0;\n for (let match = links.exec(cell.text); match !== null; match = links.exec(cell.text)) {\n prose(cell.text.slice(last, match.index));\n // Both groups always take part in a match, so the `?? ''` below and in the\n // label are for the type.\n const destination = (match[2] ?? '').trim();\n // A link states where its target lives; its label states only what the\n // target is called (ADR-0008). In a column the author has already typed,\n // the destination is the claim - `[see](adr/0050.md)` is a dependency on\n // that file, not on the word \"see\". An external or in-page destination\n // names no document here, so the label is what is left to try.\n const local = destination.length > 0 && !destination.startsWith('#') && !isExternal(destination);\n push(local ? destination : (match[1] ?? ''));\n last = match.index + match[0].length;\n }\n prose(cell.text.slice(last));\n return out;\n}\n\n/** Reduces a cell to its text: link labels rather than link syntax. */\nfunction flatten(text: string): string {\n return text\n .replace(MARKDOWN_LINK, '$1')\n .replace(/\\[\\[(?:[^\\]|]*\\|)?([^\\]]*)\\]\\]/g, '$1')\n .replace(/[`*_~]/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/** Where a heading's section ends: the next heading at the same level or above. */\nfunction regionEnd(scanned: ScannedDocument, index: number): number {\n const heading = scanned.headings[index] as Heading;\n for (let i = index + 1; i < scanned.headings.length; i += 1) {\n const next = scanned.headings[i] as Heading;\n if (next.level <= heading.level) return next.start;\n }\n return scanned.text.length;\n}\n\n/**\n * Reads a status declared inside a region.\n *\n * Two forms, both common: a labelled line (`**Status:** Accepted`) and a\n * sub-heading (`### Status` with the value beneath it). Only the region is\n * searched, so one decision in a register cannot inherit its neighbour's.\n */\nexport function readRegionStatus(scanned: ScannedDocument, start: number, end: number): RegionStatus | null {\n const labelled = readLabelledStatus(scanned, start, end);\n if (labelled) return labelled;\n return readHeadedStatus(scanned, start, end);\n}\n\nfunction readLabelledStatus(scanned: ScannedDocument, start: number, end: number): RegionStatus | null {\n for (const line of scanned.lines) {\n if (line.contentStart < start) continue;\n if (line.contentStart >= end) break;\n // A template's commented-out `Status: proposed | accepted` is a hint to\n // whoever fills it in, not a status the region declares, and one in code or\n // a <pre> block is an example.\n if (!isMarkdownLine(line) || line.blank || line.comment) continue;\n const match = INLINE_STATUS.exec(line.content);\n if (!match) continue;\n // `**Status:** Accepted` closes its emphasis *after* the colon, so the\n // closing marker lands in the captured value. Strip it rather than let it\n // reach the report as part of the status a reader is shown.\n const value = (match[1] as string).replace(/^[*_\\s]+/, '').replace(/[*_\\s]+$/, '');\n if (value.length === 0) continue;\n const offset = line.contentStart + line.content.lastIndexOf(value);\n return { text: value, start: offset, end: offset + value.length };\n }\n return null;\n}\n\nfunction readHeadedStatus(scanned: ScannedDocument, start: number, end: number): RegionStatus | null {\n // The upper bound decides nothing on its own: under a heading at or past\n // `end` there is no line before `end`, and the loop below stops there.\n const heading = scanned.headings.find((h) => h.start >= start && h.start < end && isStatusHeading(h.text));\n if (!heading) return null;\n\n for (const line of scanned.lines) {\n if (line.line <= heading.line) continue;\n if (line.contentStart >= end) break;\n if (line.blank || isOnlyComment(scanned, line)) continue;\n if (!isMarkdownLine(line)) return null;\n if (opensHeading(scanned, line.line)) return null;\n const trimmed = line.content.trim();\n // A bullet list under Status is a status history; the first entry is current.\n const cleaned = trimmed.replace(/^[-*+]\\s+/, '');\n const offset = line.contentStart + line.content.indexOf(trimmed) + (trimmed.length - cleaned.length);\n return { text: cleaned, start: offset, end: offset + cleaned.length };\n }\n return null;\n}\n\n/**\n * Whether a heading begins on this line, which ends a status section's search\n * for its value.\n *\n * Asked of the scanner rather than of the line's first character, because a\n * setext heading's text line starts with no `#`: under `### Status` it read as\n * the status, and a register took the next decision's title for its own.\n */\nexport function opensHeading(scanned: ScannedDocument, line: number): boolean {\n return scanned.headings.some((heading) => heading.line === line);\n}\n\n/**\n * The last `@spec-node` directive inside a region: the one written last, which\n * is the one a reader sees as the final word.\n *\n * Directives arrive in the order they were written, so each candidate starts\n * after the one before it and the comparison below only restates that. And\n * `start` is where a heading's line ends, a comment written on it included,\n * so no directive begins exactly there and `<` against `<=` decides nothing.\n */\nfunction directiveIn(directives: readonly Directive[], start: number, end: number): Directive | null {\n let found: Directive | null = null;\n for (const directive of directives) {\n if (directive.name !== 'spec-node') continue;\n if (directive.start < start || directive.end > end) continue;\n if (found === null || directive.start > found.start) found = directive;\n }\n return found;\n}\n\n/**\n * Case- and separator-insensitive comparison, matching reference folding.\n *\n * Applied to both sides of one comparison, so which case it folds to does not\n * matter; the separators take every space with them, so the trim does not\n * either; and `+` only saves work.\n */\nfunction fold(value: string): string {\n return value.trim().toLowerCase().replace(/[\\s._-]+/g, '');\n}\n\n/** The region containing an offset, innermost first. `null` when only the file does. */\nexport function regionAt(regions: readonly SpecificationRegion[], offset: number): SpecificationRegion | null {\n let best: SpecificationRegion | null = null;\n for (const region of regions) {\n // The whole-file region owns nothing in particular; it is the fallback.\n if (region.heading === null && region.row === null) continue;\n if (offset < region.start || offset >= region.end) continue;\n // No two regions of one file open at the same offset, so `>` and `>=`\n // agree here.\n if (best === null || region.start > best.start) best = region;\n }\n return best;\n}\n"]}
1
+ {"version":3,"file":"sections.js","sourceRoot":"","sources":["../src/sections.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Specification regions: the part of a file that one specification occupies.\n *\n * `spec-graph` began by assuming one specification per file, because that is\n * how MADR, KEPs and Rust RFCs are laid out. Plenty of organisations do not\n * work that way. A register, a whitepaper or a living architecture document\n * holds dozens of decisions in one file, each with its own identifier, its own\n * status and its own dependencies - and to an engine that binds a document to a\n * file, every one of them is invisible.\n *\n * The fix is small once stated: **a specification is a region of a file, not a\n * file.** A file yields at least one region - itself - and may yield more.\n * Everything downstream is unchanged, because a region produces exactly the\n * same `DocumentNode` a whole file produced.\n *\n * What this module decides is where those regions begin and end, and it is\n * deliberately hard to convince. A heading has to carry an identifier *and* the\n * section has to declare a status before it counts. One signal is not enough:\n * `## Q3 2026 Roadmap` parses as family `Q`, number 3, and `## v1.2.0` in a\n * changelog parses as family `v`, number 1. Neither is a specification, and\n * neither declares a status.\n */\n\nimport { attr, type Directive } from './directives.js';\nimport { HAS_LETTER_OR_DIGIT, isExternal, parsePrefixedRef } from './identity.js';\nimport { isStatusHeading } from './lifecycle.js';\nimport {\n isMarkdownLine,\n isOnlyComment,\n type Heading,\n type Range,\n type ScannedDocument,\n type Table,\n type TableCell,\n type TableRow,\n} from './markdown.js';\nimport type { EdgeKind } from './types.js';\n\n/** A status as written, and where it was written. */\nexport interface RegionStatus {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\n/** A relation read from a table column rather than from prose. */\nexport interface TableRelation {\n readonly kind: EdgeKind;\n readonly inverted: boolean;\n readonly target: string;\n readonly start: number;\n readonly end: number;\n /** The column header that gave it its meaning, for the diagnostic. */\n readonly column: string;\n}\n\nexport interface SpecificationRegion {\n /** The heading that opens the region, or `null` for the file or a table row. */\n readonly heading: Heading | null;\n /** The table row that is the region, when it is one. */\n readonly row: TableRow | null;\n /** Offset the region starts at. */\n readonly start: number;\n /** Offset just past the region. */\n readonly end: number;\n /** Identifier read from the heading or the identifier column. */\n readonly declaredId: string | null;\n readonly title: string | null;\n readonly status: RegionStatus | null;\n /** A `@spec-node` directive inside the region, when there is one. */\n readonly directive: Directive | null;\n /** Relations declared by column, empty for a heading region. */\n readonly relations: readonly TableRelation[];\n /**\n * Cells whose content is already accounted for as a typed relation.\n *\n * Prose scanning skips these, so a link in a `Depends on` column produces one\n * typed edge rather than a typed edge and a neutral citation beside it.\n */\n readonly claimed: readonly Range[];\n}\n\n/** Column headers that name the row's identifier. */\nconst ID_COLUMNS = /^(?:id|ids|ref|reference|key|no|number|#|adr|rfc|kep|oi|decision|spec|specification)$/;\n\n/** Column headers that name the row's status. */\nconst STATUS_COLUMNS = /^(?:status|state|stage|lifecycle|phase)$/;\n\n/** Column headers that name the row's title. */\nconst TITLE_COLUMNS = /^(?:title|name|summary|description|subject|decision|topic)$/;\n\n/**\n * Column headers that declare a relation.\n *\n * Written the way a header is written - \"Depends on\", \"Superseded by\" - rather\n * than the way a front-matter key is, because that is what an author types at\n * the top of a column.\n */\nconst RELATION_COLUMNS: Readonly<Record<string, { kind: EdgeKind; inverted: boolean }>> = {\n 'depends on': { kind: 'depends-on', inverted: false },\n 'depends-on': { kind: 'depends-on', inverted: false },\n dependencies: { kind: 'depends-on', inverted: false },\n requires: { kind: 'depends-on', inverted: false },\n supersedes: { kind: 'supersedes', inverted: false },\n replaces: { kind: 'supersedes', inverted: false },\n 'superseded by': { kind: 'supersedes', inverted: true },\n 'replaced by': { kind: 'supersedes', inverted: true },\n 'blocked by': { kind: 'blocked-by', inverted: false },\n 'blocked on': { kind: 'blocked-by', inverted: false },\n blocks: { kind: 'blocked-by', inverted: true },\n amends: { kind: 'amends', inverted: false },\n extends: { kind: 'amends', inverted: false },\n assumes: { kind: 'assumes', inverted: false },\n 'delegates to': { kind: 'delegates-to', inverted: false },\n 'delegated to': { kind: 'delegates-to', inverted: false },\n 'tracked in': { kind: 'delegates-to', inverted: false },\n related: { kind: 'relates-to', inverted: false },\n 'related to': { kind: 'relates-to', inverted: false },\n 'see also': { kind: 'relates-to', inverted: false },\n references: { kind: 'references', inverted: false },\n};\n\n/** Cell values that mean \"nothing here\". */\nconst MARKDOWN_LINK = /!?\\[([^\\]]*)\\]\\(([^)]*)\\)/g;\nconst EMPTY_CELL = /^(?:-+|—|–|n\\/?a|none|nil|tbd|\\.|_+)$/i;\n\n/** `## ADR-0007: Sharding` - an identifier at the very start of a heading. */\nconst HEADING_ID = /^\\s*([A-Za-z]{1,15}[\\s._-]?\\d{1,6})\\b/;\n\n/** `**Status:** Accepted`, `Status: Accepted`, `*Status* : Accepted`. */\nconst INLINE_STATUS = /^[ \\t>]*[*_]{0,2}\\s*status\\s*[*_]{0,2}\\s*:\\s*(.+?)\\s*$/im;\n\n/**\n * Finds every specification in a file.\n *\n * The first entry is always the file itself, so a caller that ignores the rest\n * behaves exactly as it did before regions existed.\n */\nexport function findSpecificationRegions(\n scanned: ScannedDocument,\n directives: readonly Directive[],\n /** The file's own identifier, so its title heading is not read as a sub-region. */\n fileId: string,\n): SpecificationRegion[] {\n // The file's own relations come from its front matter and prose, never from\n // here, and it claims no cell: nothing reads either list off this region.\n const whole: SpecificationRegion = {\n heading: null,\n row: null,\n start: scanned.bodyStart,\n end: scanned.text.length,\n declaredId: null,\n title: null,\n status: null,\n directive: null,\n relations: [],\n claimed: [],\n };\n\n const regions: SpecificationRegion[] = [];\n const folded = fold(fileId);\n const fileRef = parsePrefixedRef(fileId);\n\n for (let i = 0; i < scanned.headings.length; i += 1) {\n const heading = scanned.headings[i] as Heading;\n const declaredId = HEADING_ID.exec(heading.text)?.[1];\n if (declaredId === undefined) continue;\n // The file's own title heading names the file, not a region inside it.\n if (fold(declaredId) === folded) continue;\n // Padding is not part of an identity anywhere else - `ADR-40`, `ADR-040`\n // and `ADR-0040` all resolve to one document - so a heading that spells the\n // number differently from the file name is still that file's own title.\n // Comparing the text alone made `# ADR-040` inside `0040-enforce.md` a\n // region within the file it names: one decision, two nodes, and a citation\n // arriving at whichever spelling it happened to use.\n // `HEADING_ID` captures only what `PREFIXED_ID` parses, so `ref` is never\n // null here; the check is for the type.\n const ref = parsePrefixedRef(declaredId);\n if (ref !== null && fileRef !== null && ref.family === fileRef.family && ref.number === fileRef.number) continue;\n\n const end = regionEnd(scanned, i);\n const directive = directiveIn(directives, heading.end, end);\n const status = readRegionStatus(scanned, heading.end, end);\n\n // Two independent signals are required. An identifier alone matches\n // `## Q3 2026 Roadmap` and `## v1.2.0`; a status alone matches every\n // ordinary `## Status` section in a normal ADR.\n if (status === null && directive === null) continue;\n\n // A directive's id wins, but only if it is a name. One that is not - the\n // lone backslash `id=\\\"ADR-9\\\"` parses to, written inside a string - would\n // be discarded when the region is identified, and a region with nothing\n // to go by falls back to the file's own name: the file then contained\n // itself, and the section vanished. The heading's id is the one to keep.\n const directiveId = directive ? attr(directive, 'id')?.value : undefined;\n\n regions.push({\n heading,\n row: null,\n start: heading.start,\n end,\n declaredId: directiveId !== undefined && HAS_LETTER_OR_DIGIT.test(directiveId) ? directiveId : declaredId,\n title: heading.text,\n status,\n directive,\n relations: [],\n // Prose inside a section is prose: a heading region claims no cell.\n claimed: [],\n });\n }\n\n return [whole, ...regions, ...findTableRegions(scanned)];\n}\n\n/* -------------------------------------------------------------------------- */\n/* Registers kept as tables */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Reads a table whose columns describe specifications.\n *\n * A table qualifies when it has an identifier column *and* either a status\n * column or at least one relation column. Two signals again, for the same\n * reason: a table of identifiers and prose is a citation list, and promoting\n * every row of it to a specification would invent a register nobody wrote.\n */\nexport function findTableRegions(scanned: ScannedDocument): SpecificationRegion[] {\n const out: SpecificationRegion[] = [];\n\n for (const table of scanned.tables) {\n const schema = readSchema(table);\n if (schema === null) continue;\n\n for (const row of table.rows) {\n const idCell = row.cells[schema.id];\n if (!idCell) continue;\n const id = flatten(idCell.text);\n // A row is named by its id cell or not at all. An empty one, a\n // placeholder, or punctuation alone - `?` for a row nobody has numbered\n // yet - names nothing, and a region with no name fell back to the file's:\n // the register then contained itself, and the row vanished.\n if (!HAS_LETTER_OR_DIGIT.test(id) || EMPTY_CELL.test(id)) continue;\n\n // `row.cells[null]` is undefined too, so the null checks on the optional\n // columns are for the type; and `statusText` is read only beside a cell.\n const statusCell = schema.status === null ? undefined : row.cells[schema.status];\n const statusText = statusCell ? flatten(statusCell.text) : '';\n const status: RegionStatus | null =\n statusCell && statusText.length > 0 && !EMPTY_CELL.test(statusText)\n ? { text: statusText, start: statusCell.start, end: statusCell.end }\n : null;\n\n const titleCell = schema.title === null ? undefined : row.cells[schema.title];\n const title = titleCell ? flatten(titleCell.text) : null;\n\n const relations: TableRelation[] = [];\n // The status cell is left to prose, as a status line under a heading is:\n // `Superseded by ADR-0002` there names the row's successor, and claimed\n // it named nothing at all.\n const claimed: Range[] = [{ start: idCell.start, end: idCell.end }];\n\n for (const [column, relation] of schema.relations) {\n const cell = row.cells[column];\n if (!cell) continue;\n claimed.push({ start: cell.start, end: cell.end });\n for (const target of splitTargets(cell)) {\n relations.push({\n kind: relation.kind,\n inverted: relation.inverted,\n target: target.text,\n start: target.start,\n end: target.end,\n column: (table.headers[column] as TableCell).text,\n });\n }\n }\n\n out.push({\n heading: null,\n row,\n start: row.start,\n end: row.end,\n declaredId: id,\n title: title !== null && title.length > 0 ? title : null,\n status,\n directive: null,\n relations,\n claimed,\n });\n }\n }\n\n return out;\n}\n\n/**\n * Whether spec-graph reads a table as a register: an identifier column, and a\n * status column or a relation column beside it. Such a table's status column\n * describes its rows, never the document holding it.\n */\nexport function isRegisterTable(table: Table): boolean {\n return readSchema(table) !== null;\n}\n\ninterface TableSchema {\n readonly id: number;\n readonly status: number | null;\n readonly title: number | null;\n readonly relations: readonly (readonly [number, { kind: EdgeKind; inverted: boolean }])[];\n}\n\nfunction readSchema(table: Table): TableSchema | null {\n let id: number | null = null;\n let status: number | null = null;\n let title: number | null = null;\n const relations: [number, { kind: EdgeKind; inverted: boolean }][] = [];\n\n table.headers.forEach((header, column) => {\n const name = normaliseHeader(header.text);\n if (id === null && ID_COLUMNS.test(name)) {\n id = column;\n return;\n }\n if (status === null && STATUS_COLUMNS.test(name)) {\n status = column;\n return;\n }\n const relation = RELATION_COLUMNS[name];\n if (relation) {\n relations.push([column, relation]);\n return;\n }\n if (title === null && TITLE_COLUMNS.test(name)) title = column;\n });\n\n // Without an id column every row would be skipped for want of an id cell;\n // this says so before reading any of them.\n if (id === null) return null;\n if (status === null && relations.length === 0) return null;\n return { id, status, title, relations };\n}\n\nfunction normaliseHeader(text: string): string {\n return flatten(text)\n .toLowerCase()\n .replace(/[^a-z0-9/#\\s-]/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/** Splits a cell into the identifiers it lists, keeping each one's offset. */\nfunction splitTargets(cell: TableCell): { text: string; start: number; end: number }[] {\n const out: { text: string; start: number; end: number }[] = [];\n // Every target is reported at the cell's span. A cell is short, and an offset\n // recovered back through a flattening is an offset that can drift.\n const push = (raw: string): void => {\n const target = raw.trim();\n if (target.length === 0 || EMPTY_CELL.test(target)) return;\n out.push({ text: target, start: cell.start, end: cell.end });\n };\n const prose = (segment: string): void => {\n for (const piece of flatten(segment).split(/\\s*(?:[,;]|\\band\\b)\\s*/i)) push(piece);\n };\n\n // Links are taken out whole rather than flattened with everything else: a\n // path would otherwise be cut in half by its own slash, and its underscores\n // stripped as emphasis.\n // `matchAll` scans a copy of the pattern. `prose` calls `flatten`, which\n // drives the shared one, and one /g regex advanced from inside its own scan\n // resets its cursor and never terminates.\n let last = 0;\n for (const match of cell.text.matchAll(MARKDOWN_LINK)) {\n prose(cell.text.slice(last, match.index));\n // Both groups always take part in a match, so the `?? ''` below and in the\n // label are for the type.\n const destination = (match[2] ?? '').trim();\n // A link states where its target lives; its label states only what the\n // target is called (ADR-0008). In a column the author has already typed,\n // the destination is the claim - `[see](adr/0050.md)` is a dependency on\n // that file, not on the word \"see\". An external or in-page destination\n // names no document here, so the label is what is left to try.\n const local = destination.length > 0 && !destination.startsWith('#') && !isExternal(destination);\n push(local ? destination : (match[1] ?? ''));\n last = match.index + match[0].length;\n }\n prose(cell.text.slice(last));\n return out;\n}\n\n/** Reduces a cell to its text: link labels rather than link syntax. */\nfunction flatten(text: string): string {\n return text\n .replace(MARKDOWN_LINK, '$1')\n .replace(/\\[\\[(?:[^\\]|]*\\|)?([^\\]]*)\\]\\]/g, '$1')\n .replace(/[`*_~]/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/** Where a heading's section ends: the next heading at the same level or above. */\nfunction regionEnd(scanned: ScannedDocument, index: number): number {\n const heading = scanned.headings[index] as Heading;\n for (let i = index + 1; i < scanned.headings.length; i += 1) {\n const next = scanned.headings[i] as Heading;\n if (next.level <= heading.level) return next.start;\n }\n return scanned.text.length;\n}\n\n/**\n * Reads a status declared inside a region.\n *\n * Two forms, both common: a labelled line (`**Status:** Accepted`) and a\n * sub-heading (`### Status` with the value beneath it). Only the region is\n * searched, so one decision in a register cannot inherit its neighbour's.\n */\nexport function readRegionStatus(scanned: ScannedDocument, start: number, end: number): RegionStatus | null {\n const labelled = readLabelledStatus(scanned, start, end);\n if (labelled) return labelled;\n return readHeadedStatus(scanned, start, end);\n}\n\nfunction readLabelledStatus(scanned: ScannedDocument, start: number, end: number): RegionStatus | null {\n for (const line of scanned.lines) {\n if (line.contentStart < start) continue;\n if (line.contentStart >= end) break;\n // A template's commented-out `Status: proposed | accepted` is a hint to\n // whoever fills it in, not a status the region declares, and one in code or\n // a <pre> block is an example.\n if (!isMarkdownLine(line) || line.blank || line.comment) continue;\n const match = INLINE_STATUS.exec(line.content);\n if (!match) continue;\n // `**Status:** Accepted` closes its emphasis *after* the colon, so the\n // closing marker lands in the captured value. Strip it rather than let it\n // reach the report as part of the status a reader is shown.\n const value = (match[1] as string).replace(/^[*_\\s]+/, '').replace(/[*_\\s]+$/, '');\n if (value.length === 0) continue;\n const offset = line.contentStart + line.content.lastIndexOf(value);\n return { text: value, start: offset, end: offset + value.length };\n }\n return null;\n}\n\nfunction readHeadedStatus(scanned: ScannedDocument, start: number, end: number): RegionStatus | null {\n // The upper bound decides nothing on its own: under a heading at or past\n // `end` there is no line before `end`, and the loop below stops there.\n const heading = scanned.headings.find((h) => h.start >= start && h.start < end && isStatusHeading(h.text));\n if (!heading) return null;\n\n for (const line of scanned.lines) {\n if (line.line <= heading.line) continue;\n if (line.contentStart >= end) break;\n if (line.blank || isOnlyComment(scanned, line)) continue;\n if (!isMarkdownLine(line)) return null;\n if (opensHeading(scanned, line.line)) return null;\n const trimmed = line.content.trim();\n // A bullet list under Status is a status history; the first entry is current.\n const cleaned = trimmed.replace(/^[-*+]\\s+/, '');\n const offset = line.contentStart + line.content.indexOf(trimmed) + (trimmed.length - cleaned.length);\n return { text: cleaned, start: offset, end: offset + cleaned.length };\n }\n return null;\n}\n\n/**\n * Whether a heading begins on this line, which ends a status section's search\n * for its value.\n *\n * Asked of the scanner rather than of the line's first character, because a\n * setext heading's text line starts with no `#`: under `### Status` it read as\n * the status, and a register took the next decision's title for its own.\n */\nexport function opensHeading(scanned: ScannedDocument, line: number): boolean {\n return scanned.headings.some((heading) => heading.line === line);\n}\n\n/**\n * The last `@spec-node` directive inside a region: the one written last, which\n * is the one a reader sees as the final word.\n *\n * Directives arrive in the order they were written, so each candidate starts\n * after the one before it and the comparison below only restates that. And\n * `start` is where a heading's line ends, a comment written on it included,\n * so no directive begins exactly there and `<` against `<=` decides nothing.\n */\nfunction directiveIn(directives: readonly Directive[], start: number, end: number): Directive | null {\n let found: Directive | null = null;\n for (const directive of directives) {\n if (directive.name !== 'spec-node') continue;\n if (directive.start < start || directive.end > end) continue;\n if (found === null || directive.start > found.start) found = directive;\n }\n return found;\n}\n\n/**\n * Case- and separator-insensitive comparison, matching reference folding.\n *\n * Applied to both sides of one comparison, so which case it folds to does not\n * matter; the separators take every space with them, so the trim does not\n * either; and `+` only saves work.\n */\nfunction fold(value: string): string {\n return value.trim().toLowerCase().replace(/[\\s._-]+/g, '');\n}\n\n/** The region containing an offset, innermost first. `null` when only the file does. */\nexport function regionAt(regions: readonly SpecificationRegion[], offset: number): SpecificationRegion | null {\n let best: SpecificationRegion | null = null;\n for (const region of regions) {\n // The whole-file region owns nothing in particular; it is the fallback.\n if (region.heading === null && region.row === null) continue;\n if (offset < region.start || offset >= region.end) continue;\n // No two regions of one file open at the same offset, so `>` and `>=`\n // agree here.\n if (best === null || region.start > best.start) best = region;\n }\n return best;\n}\n"]}
package/dist/state.d.ts CHANGED
@@ -41,5 +41,17 @@ export interface ResolvedState {
41
41
  }
42
42
  /** Collects every state signal on an item and decides between them. */
43
43
  export declare function resolveItemState(input: StateInput): ResolvedState;
44
+ /**
45
+ * `exec` from past where the last match began.
46
+ *
47
+ * The other scans over a /g pattern use `matchAll`, which steps past an empty
48
+ * match. This one cannot: it resumes inside its match, on the stop a marker's
49
+ * qualifier took, so that the stop can start the next statement. No marker is
50
+ * empty, so no match is, and the resume is always past where its match began.
51
+ * A marker emptied by mistake would match empty at the start of every line,
52
+ * and `exec` would find it there for ever; this steps past it, and the marker
53
+ * tests fail instead.
54
+ */
55
+ export declare function execPast(pattern: RegExp, text: string, index: number): RegExpExecArray | null;
44
56
  /** Exposed for the query language, which lets users filter on these names. */
45
57
  export declare const KNOWN_STATE_WORDS: readonly string[];
package/dist/state.js CHANGED
@@ -292,7 +292,7 @@ function buildMarkerPattern() {
292
292
  function findMarkers(body) {
293
293
  const out = [];
294
294
  MARKER_PATTERN.lastIndex = 0;
295
- for (let m = MARKER_PATTERN.exec(body); m !== null; m = MARKER_PATTERN.exec(body)) {
295
+ for (let m = MARKER_PATTERN.exec(body); m !== null; m = execPast(MARKER_PATTERN, body, m.index)) {
296
296
  const phrase = m[2];
297
297
  const emphasisOpen = m[1];
298
298
  const emphasisClose = m[3];
@@ -320,6 +320,22 @@ function findMarkers(body) {
320
320
  }
321
321
  return out;
322
322
  }
323
+ /**
324
+ * `exec` from past where the last match began.
325
+ *
326
+ * The other scans over a /g pattern use `matchAll`, which steps past an empty
327
+ * match. This one cannot: it resumes inside its match, on the stop a marker's
328
+ * qualifier took, so that the stop can start the next statement. No marker is
329
+ * empty, so no match is, and the resume is always past where its match began.
330
+ * A marker emptied by mistake would match empty at the start of every line,
331
+ * and `exec` would find it there for ever; this steps past it, and the marker
332
+ * tests fail instead.
333
+ */
334
+ export function execPast(pattern, text, index) {
335
+ if (pattern.lastIndex <= index)
336
+ pattern.lastIndex = index + 1;
337
+ return pattern.exec(text);
338
+ }
323
339
  /** Built once: this used to be rebuilt for every item in the corpus. */
324
340
  function markerLookup() {
325
341
  const map = new Map();
package/dist/state.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Item state resolution.\n *\n * The premise of this module is that `- [ ]` and `- [x]` are the *least*\n * reliable statement a document makes about an obligation. Real specifications\n * record outcomes in prose, on a continuation line, days after the checkbox was\n * written and nobody went back to tick it:\n *\n * ```md\n * - [ ] Should the write path shard before the migration?\n * **Resolved (2026-03):** no - one node holds three years of growth.\n * ```\n *\n * A grep for `- [ ]` calls that an open question and re-opens a settled debate.\n * A grep for `- [x]` misses it entirely. spec-graph reads both signals, lets the\n * more specific one win, and *reports the disagreement* rather than hiding it,\n * because a checkbox that contradicts its own body is itself a defect worth\n * knowing about.\n */\n\nimport type { Directive } from './directives.js';\nimport { attr } from './directives.js';\nimport type { ListItem } from './markdown.js';\nimport { refOf, type LineIndex } from './source.js';\nimport { OPENNESS_OF, type Disposition, type Openness, type SourceRef, type StateSignal } from './types.js';\n\n/** Which signal wins when two disagree. Higher is more specific. */\nconst SIGNAL_PRIORITY: Readonly<Record<StateSignal['source'], number>> = {\n directive: 5,\n marker: 4,\n strikethrough: 3,\n checkbox: 2,\n section: 1,\n default: 0,\n};\n\n/**\n * Checkbox characters.\n *\n * `[ ]` and `[x]` are universal; the rest come from conventions that several\n * ecosystems share (`[~]` partial, `[-]` dropped, `[?]` question, `[/]` in\n * progress). Reading them costs nothing and refusing to would throw away the\n * one place a document states its nuance unambiguously.\n */\nconst CHECKBOX_STATE: Readonly<Record<string, Disposition>> = {\n ' ': 'unresolved',\n x: 'satisfied',\n X: 'satisfied',\n '+': 'satisfied',\n '~': 'narrowed',\n '/': 'narrowed',\n '-': 'rejected',\n '?': 'unresolved',\n '!': 'unresolved',\n '*': 'unresolved',\n};\n\n/**\n * Prose markers, by the state they announce.\n *\n * Matched only in the qualified forms real documents use - `**Resolved:**`,\n * `RESOLVED -`, `**Moot**` - never as bare words, so ordinary prose such as\n * \"we resolved to keep the queue\" does not close an item.\n */\nconst MARKERS: Readonly<Record<Disposition, readonly string[]>> = {\n satisfied: [\n 'resolved',\n 'answered',\n 'decided',\n 'settled',\n 'done',\n 'complete',\n 'completed',\n 'closed',\n 'fixed',\n 'shipped',\n 'addressed',\n 'implemented',\n 'solved',\n 'confirmed',\n ],\n narrowed: [\n 'partially resolved',\n 'partially answered',\n 'partially done',\n 'partly resolved',\n 'narrowed',\n 'narrowed to',\n 'scoped down',\n 'reduced scope',\n 'reduced to',\n 'partial',\n 'in progress',\n 'remaining',\n 'split',\n ],\n delegated: [\n 'delegated',\n 'delegated to',\n 'moved to',\n 'tracked in',\n 'tracked by',\n 'handed off',\n 'handed off to',\n 'handed to',\n 'deferred to',\n 'follow up in',\n 'follow-up in',\n 'followup in',\n 'continued in',\n 'owned by',\n ],\n 'accepted-debt': [\n 'accepted debt',\n 'accepted as debt',\n 'accepted risk',\n 'known limitation',\n 'known issue',\n 'known gap',\n 'technical debt',\n 'tech debt',\n 'wontfix',\n \"won't fix\",\n 'will not fix',\n 'by design',\n 'tolerated',\n 'living with it',\n ],\n rejected: [\n 'rejected',\n 'declined',\n 'dropped',\n 'not doing',\n 'will not do',\n 'abandoned',\n 'cancelled',\n 'canceled',\n 'withdrawn',\n ],\n obviated: [\n 'no longer applicable',\n 'no longer relevant',\n 'no longer needed',\n 'overtaken by events',\n 'premise invalid',\n 'obviated',\n 'obsolete',\n 'not applicable',\n 'moot',\n 'void',\n 'n/a',\n 'obe',\n ],\n unresolved: ['unresolved', 'still open', 'open question', 'tbd', 'undecided', 'reopened'],\n};\n\n/** Words accepted in a `state=` attribute, including friendly synonyms. */\nconst STATE_ALIASES: Readonly<Record<string, Disposition>> = {\n open: 'unresolved',\n unresolved: 'unresolved',\n todo: 'unresolved',\n narrowed: 'narrowed',\n partial: 'narrowed',\n delegated: 'delegated',\n satisfied: 'satisfied',\n resolved: 'satisfied',\n done: 'satisfied',\n closed: 'satisfied',\n 'accepted-debt': 'accepted-debt',\n debt: 'accepted-debt',\n wontfix: 'accepted-debt',\n rejected: 'rejected',\n declined: 'rejected',\n obviated: 'obviated',\n moot: 'obviated',\n};\n\nconst MARKER_PATTERN = buildMarkerPattern();\nconst MARKER_LOOKUP = markerLookup();\n\nexport interface StateInput {\n readonly file: string;\n readonly index: LineIndex;\n readonly item: ListItem;\n /** Heading path the item sits under. */\n readonly section: readonly string[];\n /** A `@spec-item` directive attached to the item, when there is one. */\n readonly directive: Directive | null;\n /** True when the item sits under a heading that declares obligations. */\n readonly inObligationSection: boolean;\n}\n\nexport interface ResolvedState {\n readonly disposition: Disposition;\n readonly openness: Openness;\n readonly evidence: StateSignal;\n /** Signals that disagree with `evidence` about how open the item is. */\n readonly conflicts: readonly StateSignal[];\n}\n\n/** Collects every state signal on an item and decides between them. */\nexport function resolveItemState(input: StateInput): ResolvedState {\n const { file, index, item } = input;\n const signals: StateSignal[] = [];\n\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n if (input.directive) {\n const declared = attr(input.directive, 'state');\n if (declared) {\n const mapped = STATE_ALIASES[declared.value.toLowerCase()];\n if (mapped) {\n signals.push({\n source: 'directive',\n disposition: mapped,\n raw: declared.value,\n at: at(declared.start, declared.end),\n });\n }\n }\n }\n\n // Markers are searched in the masked body: a fenced example nested under an\n // item must never be able to close it.\n for (const found of findMarkers(item.maskedBody)) {\n signals.push({\n source: 'marker',\n disposition: found.disposition,\n raw: found.raw,\n at: at(item.textStart + found.start, item.textStart + found.end),\n });\n }\n\n const struck = strikethroughOf(item.firstLine);\n if (struck) {\n signals.push({\n source: 'strikethrough',\n disposition: 'satisfied',\n raw: struck,\n at: at(item.textStart, item.textStart + item.firstLine.length),\n });\n }\n\n // The scanner reads a checkbox only from the ten characters above, and gives\n // it a start exactly when it gives it a character: these guards narrow types\n // and decide nothing, so their mutants are equivalent.\n if (item.checkbox !== null && item.checkboxStart !== null) {\n const mapped = CHECKBOX_STATE[item.checkbox];\n if (mapped) {\n signals.push({\n source: 'checkbox',\n disposition: mapped,\n raw: `[${item.checkbox}]`,\n at: at(item.checkboxStart, item.checkboxStart + 3),\n });\n }\n }\n\n if (input.inObligationSection) {\n signals.push({\n source: 'section',\n disposition: 'unresolved',\n // An item in an obligation section is under a heading, so the fallback\n // narrows the type and is never read.\n raw: input.section[input.section.length - 1] ?? '',\n at: at(item.start, item.end),\n });\n }\n\n if (signals.length === 0) {\n const fallback: StateSignal = {\n source: 'default',\n disposition: 'unresolved',\n raw: '',\n at: at(item.start, item.end),\n };\n return { disposition: 'unresolved', openness: 'open', evidence: fallback, conflicts: [] };\n }\n\n // The most specific signal wins; ties go to the one written last, which is\n // the one a reader of the document sees as the final word.\n //\n // Signals are pushed most specific first and markers in document order, so\n // the winner only changes on a tie, where array order and document order\n // agree. Mutants of the comparisons are equivalent for that reason; they are\n // written out so that neither fact about the pushes above is load-bearing.\n let winner = signals[0] as StateSignal;\n for (const signal of signals) {\n const better = SIGNAL_PRIORITY[signal.source] - SIGNAL_PRIORITY[winner.source];\n if (better > 0 || (better === 0 && signal.at.span.start.offset > winner.at.span.start.offset)) {\n winner = signal;\n }\n }\n\n const openness = OPENNESS_OF[winner.disposition];\n // Only disagreement about *openness* is a conflict. A body that says\n // \"Resolved\" under a ticked checkbox agrees with it; one under an empty\n // checkbox does not, and that is worth a human looking at. The winner agrees\n // with itself, so it is never among them.\n const conflicts = signals.filter(\n (signal) => signal.source !== 'section' && OPENNESS_OF[signal.disposition] !== openness,\n );\n\n return { disposition: winner.disposition, openness, evidence: winner, conflicts };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Marker matching */\n/* -------------------------------------------------------------------------- */\n\ninterface MarkerHit {\n readonly disposition: Disposition;\n readonly raw: string;\n readonly start: number;\n readonly end: number;\n}\n\nfunction buildMarkerPattern(): RegExp {\n const phrases = Object.values(MARKERS)\n .flat()\n // Longest first so `partially resolved` is not eaten by `resolved`.\n .sort((a, b) => b.length - a.length)\n .map(escapeRegExp)\n // Allow the writer to space, hyphenate or underscore a multi-word marker\n // whichever way, and to type its apostrophe straight or curly.\n .map((phrase) => phrase.replace(/\\\\?[ -]/g, '[ _\\\\-]').replace(/'/g, \"['’]\"));\n\n return new RegExp(\n // A marker only counts at the start of a statement: the start of the item,\n // a new line, after a sentence ends, or after an emphasis opener.\n String.raw`(?:^|\\n|[.?!]\\s+|[(\\[])` +\n // Skip block-quote and list markers, but only when the marker character is\n // followed by whitespace. Without that guard the `*` of `**Resolved**`\n // reads as a bullet and the emphasis wrapper is lost.\n String.raw`(?:[ \\t>•]|(?:[-*+]|\\d{1,9}[.)])[ \\t]+)*` +\n // Optional emphasis wrapper, remembered so `**Moot**` qualifies without a colon.\n String.raw`(\\*{1,2}|_{1,2})?` +\n String.raw`\\s*(${phrases.join('|')})` +\n String.raw`(\\*{1,2}|_{1,2})?` +\n // An optional dated parenthetical: `Resolved (2026-03):`.\n String.raw`\\s*(?:[(\\[][^)\\]\\n]{0,60}[)\\]])?` +\n // Optional, and validated in code below: an emphasised or shouted marker\n // stands on its own, a bare lower-case word never does.\n String.raw`\\s*([::]|[-–—]\\s|\\.|$|\\n)?`,\n 'gim',\n );\n}\n\nfunction findMarkers(body: string): MarkerHit[] {\n const out: MarkerHit[] = [];\n\n MARKER_PATTERN.lastIndex = 0;\n for (let m = MARKER_PATTERN.exec(body); m !== null; m = MARKER_PATTERN.exec(body)) {\n const phrase = m[2] as string;\n const emphasisOpen = m[1];\n const emphasisClose = m[3];\n // A dash arrives with the space after it. An absent qualifier is none of the\n // four, so what stands in for it is equivalent as long as it is not one.\n // Only the dash alternative puts a dash in the qualifier at all, so the\n // anchor on the dash test decides nothing either.\n const qualifier = m[4] ?? '';\n\n const emphasised = emphasisOpen !== undefined && emphasisClose !== undefined;\n const punctuated = qualifier === ':' || qualifier === ':' || /^[-–—]/.test(qualifier) || qualifier === '.';\n const shouted = phrase === phrase.toUpperCase() && /[A-Z]/.test(phrase);\n\n // Without one of these three the match is ordinary prose. \"We resolved to\n // keep the queue\" must not close an item.\n if (!emphasised && !punctuated && !shouted) continue;\n\n // Every phrase the pattern matches is a table phrase respelled, so this\n // narrows the type and never skips: its mutant is equivalent.\n const disposition = MARKER_LOOKUP.get(normalisePhrase(phrase));\n if (!disposition) continue;\n\n const start = (m.index ?? 0) + (m[0] as string).indexOf(phrase);\n out.push({ disposition, raw: phrase, start, end: start + phrase.length });\n\n // Overlapping alternatives would double-count; resume after this match.\n MARKER_PATTERN.lastIndex = start + phrase.length;\n }\n\n return out;\n}\n\n/** Built once: this used to be rebuilt for every item in the corpus. */\nfunction markerLookup(): Map<string, Disposition> {\n const map = new Map<string, Disposition>();\n for (const [disposition, phrases] of Object.entries(MARKERS) as [Disposition, readonly string[]][]) {\n for (const phrase of phrases) map.set(normalisePhrase(phrase), disposition);\n }\n return map;\n}\n\n/**\n * The key a phrase is looked up by, from the table and from a match alike.\n *\n * Its case and separator mutants are equivalent, because it folds both sides\n * of one lookup: folded to upper case, or with the separator dropped, the same\n * phrases share a key - no two of the table's dispositions collide without\n * their spaces - and neither a table phrase nor a match ever holds two\n * separators in a row. The apostrophe is folded for the match alone: the table\n * spells it straight.\n */\nfunction normalisePhrase(phrase: string): string {\n return phrase.toLowerCase().replace(/’/g, \"'\").replace(/[\\s_-]+/g, ' ');\n}\n\n/** Returns the struck text when the whole line, which arrives trimmed, is wrapped in `~~`. */\nfunction strikethroughOf(line: string): string | null {\n if (!line.startsWith('~~') || !line.endsWith('~~')) return null;\n const inner = line.slice(2, -2);\n // Something has to be struck: `~~~~~` is the fence of a code block nested\n // under the item, and strikes nothing.\n return /[^~]/.test(inner) && !inner.includes('~~') ? line : null;\n}\n\n/**\n * No phrase in the table holds a metacharacter today, so blanking the\n * replacement is an equivalent mutant; this keeps the dots of a future `n.a.`\n * dots, rather than any character.\n */\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Exposed for the query language, which lets users filter on these names. */\nexport const KNOWN_STATE_WORDS: readonly string[] = Object.keys(STATE_ALIASES);\n"]}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Item state resolution.\n *\n * The premise of this module is that `- [ ]` and `- [x]` are the *least*\n * reliable statement a document makes about an obligation. Real specifications\n * record outcomes in prose, on a continuation line, days after the checkbox was\n * written and nobody went back to tick it:\n *\n * ```md\n * - [ ] Should the write path shard before the migration?\n * **Resolved (2026-03):** no - one node holds three years of growth.\n * ```\n *\n * A grep for `- [ ]` calls that an open question and re-opens a settled debate.\n * A grep for `- [x]` misses it entirely. spec-graph reads both signals, lets the\n * more specific one win, and *reports the disagreement* rather than hiding it,\n * because a checkbox that contradicts its own body is itself a defect worth\n * knowing about.\n */\n\nimport type { Directive } from './directives.js';\nimport { attr } from './directives.js';\nimport type { ListItem } from './markdown.js';\nimport { refOf, type LineIndex } from './source.js';\nimport { OPENNESS_OF, type Disposition, type Openness, type SourceRef, type StateSignal } from './types.js';\n\n/** Which signal wins when two disagree. Higher is more specific. */\nconst SIGNAL_PRIORITY: Readonly<Record<StateSignal['source'], number>> = {\n directive: 5,\n marker: 4,\n strikethrough: 3,\n checkbox: 2,\n section: 1,\n default: 0,\n};\n\n/**\n * Checkbox characters.\n *\n * `[ ]` and `[x]` are universal; the rest come from conventions that several\n * ecosystems share (`[~]` partial, `[-]` dropped, `[?]` question, `[/]` in\n * progress). Reading them costs nothing and refusing to would throw away the\n * one place a document states its nuance unambiguously.\n */\nconst CHECKBOX_STATE: Readonly<Record<string, Disposition>> = {\n ' ': 'unresolved',\n x: 'satisfied',\n X: 'satisfied',\n '+': 'satisfied',\n '~': 'narrowed',\n '/': 'narrowed',\n '-': 'rejected',\n '?': 'unresolved',\n '!': 'unresolved',\n '*': 'unresolved',\n};\n\n/**\n * Prose markers, by the state they announce.\n *\n * Matched only in the qualified forms real documents use - `**Resolved:**`,\n * `RESOLVED -`, `**Moot**` - never as bare words, so ordinary prose such as\n * \"we resolved to keep the queue\" does not close an item.\n */\nconst MARKERS: Readonly<Record<Disposition, readonly string[]>> = {\n satisfied: [\n 'resolved',\n 'answered',\n 'decided',\n 'settled',\n 'done',\n 'complete',\n 'completed',\n 'closed',\n 'fixed',\n 'shipped',\n 'addressed',\n 'implemented',\n 'solved',\n 'confirmed',\n ],\n narrowed: [\n 'partially resolved',\n 'partially answered',\n 'partially done',\n 'partly resolved',\n 'narrowed',\n 'narrowed to',\n 'scoped down',\n 'reduced scope',\n 'reduced to',\n 'partial',\n 'in progress',\n 'remaining',\n 'split',\n ],\n delegated: [\n 'delegated',\n 'delegated to',\n 'moved to',\n 'tracked in',\n 'tracked by',\n 'handed off',\n 'handed off to',\n 'handed to',\n 'deferred to',\n 'follow up in',\n 'follow-up in',\n 'followup in',\n 'continued in',\n 'owned by',\n ],\n 'accepted-debt': [\n 'accepted debt',\n 'accepted as debt',\n 'accepted risk',\n 'known limitation',\n 'known issue',\n 'known gap',\n 'technical debt',\n 'tech debt',\n 'wontfix',\n \"won't fix\",\n 'will not fix',\n 'by design',\n 'tolerated',\n 'living with it',\n ],\n rejected: [\n 'rejected',\n 'declined',\n 'dropped',\n 'not doing',\n 'will not do',\n 'abandoned',\n 'cancelled',\n 'canceled',\n 'withdrawn',\n ],\n obviated: [\n 'no longer applicable',\n 'no longer relevant',\n 'no longer needed',\n 'overtaken by events',\n 'premise invalid',\n 'obviated',\n 'obsolete',\n 'not applicable',\n 'moot',\n 'void',\n 'n/a',\n 'obe',\n ],\n unresolved: ['unresolved', 'still open', 'open question', 'tbd', 'undecided', 'reopened'],\n};\n\n/** Words accepted in a `state=` attribute, including friendly synonyms. */\nconst STATE_ALIASES: Readonly<Record<string, Disposition>> = {\n open: 'unresolved',\n unresolved: 'unresolved',\n todo: 'unresolved',\n narrowed: 'narrowed',\n partial: 'narrowed',\n delegated: 'delegated',\n satisfied: 'satisfied',\n resolved: 'satisfied',\n done: 'satisfied',\n closed: 'satisfied',\n 'accepted-debt': 'accepted-debt',\n debt: 'accepted-debt',\n wontfix: 'accepted-debt',\n rejected: 'rejected',\n declined: 'rejected',\n obviated: 'obviated',\n moot: 'obviated',\n};\n\nconst MARKER_PATTERN = buildMarkerPattern();\nconst MARKER_LOOKUP = markerLookup();\n\nexport interface StateInput {\n readonly file: string;\n readonly index: LineIndex;\n readonly item: ListItem;\n /** Heading path the item sits under. */\n readonly section: readonly string[];\n /** A `@spec-item` directive attached to the item, when there is one. */\n readonly directive: Directive | null;\n /** True when the item sits under a heading that declares obligations. */\n readonly inObligationSection: boolean;\n}\n\nexport interface ResolvedState {\n readonly disposition: Disposition;\n readonly openness: Openness;\n readonly evidence: StateSignal;\n /** Signals that disagree with `evidence` about how open the item is. */\n readonly conflicts: readonly StateSignal[];\n}\n\n/** Collects every state signal on an item and decides between them. */\nexport function resolveItemState(input: StateInput): ResolvedState {\n const { file, index, item } = input;\n const signals: StateSignal[] = [];\n\n const at = (start: number, end: number): SourceRef => refOf(file, index, start, end);\n\n if (input.directive) {\n const declared = attr(input.directive, 'state');\n if (declared) {\n const mapped = STATE_ALIASES[declared.value.toLowerCase()];\n if (mapped) {\n signals.push({\n source: 'directive',\n disposition: mapped,\n raw: declared.value,\n at: at(declared.start, declared.end),\n });\n }\n }\n }\n\n // Markers are searched in the masked body: a fenced example nested under an\n // item must never be able to close it.\n for (const found of findMarkers(item.maskedBody)) {\n signals.push({\n source: 'marker',\n disposition: found.disposition,\n raw: found.raw,\n at: at(item.textStart + found.start, item.textStart + found.end),\n });\n }\n\n const struck = strikethroughOf(item.firstLine);\n if (struck) {\n signals.push({\n source: 'strikethrough',\n disposition: 'satisfied',\n raw: struck,\n at: at(item.textStart, item.textStart + item.firstLine.length),\n });\n }\n\n // The scanner reads a checkbox only from the ten characters above, and gives\n // it a start exactly when it gives it a character: these guards narrow types\n // and decide nothing, so their mutants are equivalent.\n if (item.checkbox !== null && item.checkboxStart !== null) {\n const mapped = CHECKBOX_STATE[item.checkbox];\n if (mapped) {\n signals.push({\n source: 'checkbox',\n disposition: mapped,\n raw: `[${item.checkbox}]`,\n at: at(item.checkboxStart, item.checkboxStart + 3),\n });\n }\n }\n\n if (input.inObligationSection) {\n signals.push({\n source: 'section',\n disposition: 'unresolved',\n // An item in an obligation section is under a heading, so the fallback\n // narrows the type and is never read.\n raw: input.section[input.section.length - 1] ?? '',\n at: at(item.start, item.end),\n });\n }\n\n if (signals.length === 0) {\n const fallback: StateSignal = {\n source: 'default',\n disposition: 'unresolved',\n raw: '',\n at: at(item.start, item.end),\n };\n return { disposition: 'unresolved', openness: 'open', evidence: fallback, conflicts: [] };\n }\n\n // The most specific signal wins; ties go to the one written last, which is\n // the one a reader of the document sees as the final word.\n //\n // Signals are pushed most specific first and markers in document order, so\n // the winner only changes on a tie, where array order and document order\n // agree. Mutants of the comparisons are equivalent for that reason; they are\n // written out so that neither fact about the pushes above is load-bearing.\n let winner = signals[0] as StateSignal;\n for (const signal of signals) {\n const better = SIGNAL_PRIORITY[signal.source] - SIGNAL_PRIORITY[winner.source];\n if (better > 0 || (better === 0 && signal.at.span.start.offset > winner.at.span.start.offset)) {\n winner = signal;\n }\n }\n\n const openness = OPENNESS_OF[winner.disposition];\n // Only disagreement about *openness* is a conflict. A body that says\n // \"Resolved\" under a ticked checkbox agrees with it; one under an empty\n // checkbox does not, and that is worth a human looking at. The winner agrees\n // with itself, so it is never among them.\n const conflicts = signals.filter(\n (signal) => signal.source !== 'section' && OPENNESS_OF[signal.disposition] !== openness,\n );\n\n return { disposition: winner.disposition, openness, evidence: winner, conflicts };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Marker matching */\n/* -------------------------------------------------------------------------- */\n\ninterface MarkerHit {\n readonly disposition: Disposition;\n readonly raw: string;\n readonly start: number;\n readonly end: number;\n}\n\nfunction buildMarkerPattern(): RegExp {\n const phrases = Object.values(MARKERS)\n .flat()\n // Longest first so `partially resolved` is not eaten by `resolved`.\n .sort((a, b) => b.length - a.length)\n .map(escapeRegExp)\n // Allow the writer to space, hyphenate or underscore a multi-word marker\n // whichever way, and to type its apostrophe straight or curly.\n .map((phrase) => phrase.replace(/\\\\?[ -]/g, '[ _\\\\-]').replace(/'/g, \"['’]\"));\n\n return new RegExp(\n // A marker only counts at the start of a statement: the start of the item,\n // a new line, after a sentence ends, or after an emphasis opener.\n String.raw`(?:^|\\n|[.?!]\\s+|[(\\[])` +\n // Skip block-quote and list markers, but only when the marker character is\n // followed by whitespace. Without that guard the `*` of `**Resolved**`\n // reads as a bullet and the emphasis wrapper is lost.\n String.raw`(?:[ \\t>•]|(?:[-*+]|\\d{1,9}[.)])[ \\t]+)*` +\n // Optional emphasis wrapper, remembered so `**Moot**` qualifies without a colon.\n String.raw`(\\*{1,2}|_{1,2})?` +\n String.raw`\\s*(${phrases.join('|')})` +\n String.raw`(\\*{1,2}|_{1,2})?` +\n // An optional dated parenthetical: `Resolved (2026-03):`.\n String.raw`\\s*(?:[(\\[][^)\\]\\n]{0,60}[)\\]])?` +\n // Optional, and validated in code below: an emphasised or shouted marker\n // stands on its own, a bare lower-case word never does.\n String.raw`\\s*([::]|[-–—]\\s|\\.|$|\\n)?`,\n 'gim',\n );\n}\n\nfunction findMarkers(body: string): MarkerHit[] {\n const out: MarkerHit[] = [];\n\n MARKER_PATTERN.lastIndex = 0;\n for (let m = MARKER_PATTERN.exec(body); m !== null; m = execPast(MARKER_PATTERN, body, m.index)) {\n const phrase = m[2] as string;\n const emphasisOpen = m[1];\n const emphasisClose = m[3];\n // A dash arrives with the space after it. An absent qualifier is none of the\n // four, so what stands in for it is equivalent as long as it is not one.\n // Only the dash alternative puts a dash in the qualifier at all, so the\n // anchor on the dash test decides nothing either.\n const qualifier = m[4] ?? '';\n\n const emphasised = emphasisOpen !== undefined && emphasisClose !== undefined;\n const punctuated = qualifier === ':' || qualifier === ':' || /^[-–—]/.test(qualifier) || qualifier === '.';\n const shouted = phrase === phrase.toUpperCase() && /[A-Z]/.test(phrase);\n\n // Without one of these three the match is ordinary prose. \"We resolved to\n // keep the queue\" must not close an item.\n if (!emphasised && !punctuated && !shouted) continue;\n\n // Every phrase the pattern matches is a table phrase respelled, so this\n // narrows the type and never skips: its mutant is equivalent.\n const disposition = MARKER_LOOKUP.get(normalisePhrase(phrase));\n if (!disposition) continue;\n\n const start = (m.index ?? 0) + (m[0] as string).indexOf(phrase);\n out.push({ disposition, raw: phrase, start, end: start + phrase.length });\n\n // Overlapping alternatives would double-count; resume after this match.\n MARKER_PATTERN.lastIndex = start + phrase.length;\n }\n\n return out;\n}\n\n/**\n * `exec` from past where the last match began.\n *\n * The other scans over a /g pattern use `matchAll`, which steps past an empty\n * match. This one cannot: it resumes inside its match, on the stop a marker's\n * qualifier took, so that the stop can start the next statement. No marker is\n * empty, so no match is, and the resume is always past where its match began.\n * A marker emptied by mistake would match empty at the start of every line,\n * and `exec` would find it there for ever; this steps past it, and the marker\n * tests fail instead.\n */\nexport function execPast(pattern: RegExp, text: string, index: number): RegExpExecArray | null {\n if (pattern.lastIndex <= index) pattern.lastIndex = index + 1;\n return pattern.exec(text);\n}\n\n/** Built once: this used to be rebuilt for every item in the corpus. */\nfunction markerLookup(): Map<string, Disposition> {\n const map = new Map<string, Disposition>();\n for (const [disposition, phrases] of Object.entries(MARKERS) as [Disposition, readonly string[]][]) {\n for (const phrase of phrases) map.set(normalisePhrase(phrase), disposition);\n }\n return map;\n}\n\n/**\n * The key a phrase is looked up by, from the table and from a match alike.\n *\n * Its case and separator mutants are equivalent, because it folds both sides\n * of one lookup: folded to upper case, or with the separator dropped, the same\n * phrases share a key - no two of the table's dispositions collide without\n * their spaces - and neither a table phrase nor a match ever holds two\n * separators in a row. The apostrophe is folded for the match alone: the table\n * spells it straight.\n */\nfunction normalisePhrase(phrase: string): string {\n return phrase.toLowerCase().replace(/’/g, \"'\").replace(/[\\s_-]+/g, ' ');\n}\n\n/** Returns the struck text when the whole line, which arrives trimmed, is wrapped in `~~`. */\nfunction strikethroughOf(line: string): string | null {\n if (!line.startsWith('~~') || !line.endsWith('~~')) return null;\n const inner = line.slice(2, -2);\n // Something has to be struck: `~~~~~` is the fence of a code block nested\n // under the item, and strikes nothing.\n return /[^~]/.test(inner) && !inner.includes('~~') ? line : null;\n}\n\n/**\n * No phrase in the table holds a metacharacter today, so blanking the\n * replacement is an equivalent mutant; this keeps the dots of a future `n.a.`\n * dots, rather than any character.\n */\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Exposed for the query language, which lets users filter on these names. */\nexport const KNOWN_STATE_WORDS: readonly string[] = Object.keys(STATE_ALIASES);\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descent-vtt/spec-graph",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Turn Markdown specs into a verifiable relational graph. Catches ghost handovers, stale premises and broken references in CI.",
5
5
  "keywords": [
6
6
  "adr",