@descent-vtt/spec-graph 0.8.0 → 0.9.0

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +410 -0
  2. package/README.md +102 -17
  3. package/dist/cli.d.ts +2 -2
  4. package/dist/cli.js +38 -19
  5. package/dist/cli.js.map +1 -1
  6. package/dist/directives.d.ts +9 -2
  7. package/dist/directives.js +15 -4
  8. package/dist/directives.js.map +1 -1
  9. package/dist/extract.d.ts +1 -1
  10. package/dist/extract.js +50 -16
  11. package/dist/extract.js.map +1 -1
  12. package/dist/glob.d.ts +44 -44
  13. package/dist/glob.js +152 -116
  14. package/dist/glob.js.map +1 -1
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +4 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/lifecycle.js +10 -2
  19. package/dist/lifecycle.js.map +1 -1
  20. package/dist/markdown.d.ts +53 -161
  21. package/dist/markdown.js +42 -864
  22. package/dist/markdown.js.map +1 -1
  23. package/dist/report.d.ts +23 -0
  24. package/dist/report.js +80 -0
  25. package/dist/report.js.map +1 -1
  26. package/dist/rules.js +48 -14
  27. package/dist/rules.js.map +1 -1
  28. package/dist/sections.d.ts +1 -1
  29. package/dist/sections.js +7 -3
  30. package/dist/sections.js.map +1 -1
  31. package/dist/select.d.ts +2 -2
  32. package/dist/select.js +3 -3
  33. package/dist/select.js.map +1 -1
  34. package/dist/source.d.ts +6 -19
  35. package/dist/source.js +4 -70
  36. package/dist/source.js.map +1 -1
  37. package/dist/types.d.ts +23 -3
  38. package/dist/types.js +1 -1
  39. package/dist/types.js.map +1 -1
  40. package/dist/vendor/spec-core/markdown/frontmatter.d.ts +103 -0
  41. package/dist/vendor/spec-core/markdown/frontmatter.js +459 -0
  42. package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -0
  43. package/dist/vendor/spec-core/markdown/headings.d.ts +45 -0
  44. package/dist/vendor/spec-core/markdown/headings.js +199 -0
  45. package/dist/vendor/spec-core/markdown/headings.js.map +1 -0
  46. package/dist/vendor/spec-core/markdown/index.d.ts +5 -0
  47. package/dist/vendor/spec-core/markdown/index.js +4 -0
  48. package/dist/vendor/spec-core/markdown/index.js.map +1 -0
  49. package/dist/vendor/spec-core/markdown/layout.d.ts +39 -0
  50. package/dist/vendor/spec-core/markdown/layout.js +28 -0
  51. package/dist/vendor/spec-core/markdown/layout.js.map +1 -0
  52. package/dist/vendor/spec-core/markdown/links.d.ts +22 -0
  53. package/dist/vendor/spec-core/markdown/links.js +364 -0
  54. package/dist/vendor/spec-core/markdown/links.js.map +1 -0
  55. package/dist/vendor/spec-core/markdown/lists.d.ts +22 -0
  56. package/dist/vendor/spec-core/markdown/lists.js +127 -0
  57. package/dist/vendor/spec-core/markdown/lists.js.map +1 -0
  58. package/dist/vendor/spec-core/markdown/scan.d.ts +36 -0
  59. package/dist/vendor/spec-core/markdown/scan.js +439 -0
  60. package/dist/vendor/spec-core/markdown/scan.js.map +1 -0
  61. package/dist/vendor/spec-core/markdown/syntax.d.ts +75 -0
  62. package/dist/vendor/spec-core/markdown/syntax.js +181 -0
  63. package/dist/vendor/spec-core/markdown/syntax.js.map +1 -0
  64. package/dist/vendor/spec-core/markdown/tables.d.ts +18 -0
  65. package/dist/vendor/spec-core/markdown/tables.js +86 -0
  66. package/dist/vendor/spec-core/markdown/tables.js.map +1 -0
  67. package/dist/vendor/spec-core/markdown/types.d.ts +287 -0
  68. package/dist/vendor/spec-core/markdown/types.js +9 -0
  69. package/dist/vendor/spec-core/markdown/types.js.map +1 -0
  70. package/dist/vendor/spec-core/path/index.d.ts +1 -0
  71. package/dist/vendor/spec-core/path/index.js +2 -0
  72. package/dist/vendor/spec-core/path/index.js.map +1 -0
  73. package/dist/vendor/spec-core/path/posix.d.ts +83 -0
  74. package/dist/vendor/spec-core/path/posix.js +150 -0
  75. package/dist/vendor/spec-core/path/posix.js.map +1 -0
  76. package/dist/vendor/spec-core/pattern/automaton.d.ts +129 -0
  77. package/dist/vendor/spec-core/pattern/automaton.js +340 -0
  78. package/dist/vendor/spec-core/pattern/automaton.js.map +1 -0
  79. package/dist/vendor/spec-core/pattern/charset.d.ts +58 -0
  80. package/dist/vendor/spec-core/pattern/charset.js +116 -0
  81. package/dist/vendor/spec-core/pattern/charset.js.map +1 -0
  82. package/dist/vendor/spec-core/pattern/glob.d.ts +121 -0
  83. package/dist/vendor/spec-core/pattern/glob.js +481 -0
  84. package/dist/vendor/spec-core/pattern/glob.js.map +1 -0
  85. package/dist/vendor/spec-core/pattern/index.d.ts +6 -0
  86. package/dist/vendor/spec-core/pattern/index.js +4 -0
  87. package/dist/vendor/spec-core/pattern/index.js.map +1 -0
  88. package/dist/{regex.d.ts → vendor/spec-core/pattern/regex.d.ts} +20 -29
  89. package/dist/{regex.js → vendor/spec-core/pattern/regex.js} +40 -49
  90. package/dist/vendor/spec-core/pattern/regex.js.map +1 -0
  91. package/dist/vendor/spec-core/text/index.d.ts +2 -0
  92. package/dist/vendor/spec-core/text/index.js +2 -0
  93. package/dist/vendor/spec-core/text/index.js.map +1 -0
  94. package/dist/vendor/spec-core/text/lines.d.ts +72 -0
  95. package/dist/vendor/spec-core/text/lines.js +156 -0
  96. package/dist/vendor/spec-core/text/lines.js.map +1 -0
  97. package/dist/yaml.d.ts +44 -12
  98. package/dist/yaml.js +115 -206
  99. package/dist/yaml.js.map +1 -1
  100. package/package.json +3 -2
  101. package/src/vendor/spec-core/LICENSE +21 -0
  102. package/src/vendor/spec-core/README.md +8 -0
  103. package/dist/regex.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sourceRoot":"","sources":["../src/select.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The selector language.\n *\n * Rules and users ask the graph the same kinds of question, so they use the same\n * machinery. Every built-in diagnostic is a path query plus a message; anything\n * a rule can find, `spec-graph query` can find too, which means a team can\n * express a convention spec-graph never anticipated without writing a plugin.\n *\n * ```text\n * item[openness=open] -delegates-to-> document[phase=retired]\n * document[phase=active] -assumes,depends-on-> document[phase=retired]\n * document =supersedes=> document[phase=active]\n * item[state=obviated] <-assumes- *\n * *[path^=docs/adr] -blocked-by-> item[openness=open]\n * ```\n *\n * A query evaluates to **paths**, not endpoints. A rule that has the whole path\n * can say \"ADR-0004 line 31 delegates this to ADR-0002, which was retired in\n * March\" instead of naming two documents and leaving the reader to reconstruct\n * the relationship.\n */\n\nimport { receptivityOf } from './lifecycle.js';\nimport { compilePattern, PatternError, type Matcher } from './regex.js';\nimport { documentOf } from './resolve.js';\nimport type { SpecGraph } from './graph.js';\nimport { EDGE_KINDS, type Edge, type EdgeKind, type NodeKind, type SpecNode } from './types.js';\n\n/* -------------------------------------------------------------------------- */\n/* Shapes */\n/* -------------------------------------------------------------------------- */\n\nexport type Operator = '=' | '!=' | '^=' | '$=' | '*=' | '~=' | 'exists';\n\nexport interface Predicate {\n readonly key: string;\n readonly operator: Operator;\n readonly value: string;\n}\n\nexport interface NodeMatcher {\n /** `null` matches both documents and items. */\n readonly kind: NodeKind | null;\n readonly predicates: readonly Predicate[];\n}\n\nexport interface StepSpec {\n readonly direction: 'out' | 'in';\n /** `null` matches any edge kind. */\n readonly kinds: readonly EdgeKind[] | null;\n /** Follow the relation transitively, taking the shortest path to each node. */\n readonly transitive: boolean;\n readonly node: NodeMatcher;\n}\n\nexport interface QuerySpec {\n readonly start: NodeMatcher;\n readonly steps: readonly StepSpec[];\n}\n\n/** One path through the graph. `edges` always has one fewer entry than `nodes`. */\nexport interface Match {\n readonly nodes: readonly SpecNode[];\n readonly edges: readonly Edge[];\n}\n\nexport class QueryError extends Error {\n /** Offset into the query string where the problem starts. */\n readonly offset: number;\n\n constructor(message: string, offset: number) {\n super(message);\n this.name = 'QueryError';\n this.offset = offset;\n }\n}\n\n/** Guards against a pathological query fanning out over a huge corpus. */\nexport const DEFAULT_MATCH_LIMIT = 10_000;\n\n/* -------------------------------------------------------------------------- */\n/* Parsing */\n/* -------------------------------------------------------------------------- */\n\nconst NODE_KINDS: Readonly<Record<string, NodeKind | null>> = {\n document: 'document',\n documents: 'document',\n doc: 'document',\n docs: 'document',\n item: 'item',\n items: 'item',\n node: null,\n nodes: null,\n any: null,\n '*': null,\n};\n\n/** Compiles a selector string into a {@link QuerySpec}. */\nexport function parseQuery(source: string): QuerySpec {\n const parser = new Parser(source);\n const start = parser.parseNodeMatcher();\n const steps: StepSpec[] = [];\n parser.skipSpace();\n while (!parser.atEnd()) {\n steps.push(parser.parseStep());\n parser.skipSpace();\n }\n return { start, steps };\n}\n\nclass Parser {\n private readonly source: string;\n private position = 0;\n\n constructor(source: string) {\n this.source = source;\n }\n\n atEnd(): boolean {\n return this.position >= this.source.length;\n }\n\n skipSpace(): void {\n while (this.position < this.source.length && /\\s/.test(this.source[this.position] as string)) this.position += 1;\n }\n\n parseNodeMatcher(): NodeMatcher {\n this.skipSpace();\n let kind: NodeKind | null = null;\n const word = /^[A-Za-z]+|^\\*/.exec(this.source.slice(this.position));\n if (word) {\n const text = (word[0] as string).toLowerCase();\n if (!(text in NODE_KINDS)) {\n throw new QueryError(\n `unknown node type \"${word[0]}\", expected one of: document, item, * (any)`,\n this.position,\n );\n }\n kind = NODE_KINDS[text] as NodeKind | null;\n this.position += (word[0] as string).length;\n } else if (this.source[this.position] !== '[') {\n throw new QueryError('expected a node type (document, item or *) or a [predicate]', this.position);\n }\n\n const predicates: Predicate[] = [];\n while (this.source[this.position] === '[') predicates.push(this.parsePredicate());\n return { kind, predicates };\n }\n\n private parsePredicate(): Predicate {\n this.position += 1;\n const keyMatch = /^[A-Za-z_][A-Za-z0-9_.:-]*/.exec(this.source.slice(this.position));\n if (!keyMatch) throw new QueryError('expected an attribute name after \"[\"', this.position);\n const key = (keyMatch[0] as string).toLowerCase();\n this.position += (keyMatch[0] as string).length;\n\n if (this.source[this.position] === ']') {\n this.position += 1;\n return { key, operator: 'exists', value: '' };\n }\n\n const operatorMatch = /^(!=|\\^=|\\$=|\\*=|~=|=)/.exec(this.source.slice(this.position));\n if (!operatorMatch) {\n throw new QueryError(\n `expected an operator (=, !=, ^=, $=, *=, ~=) or \"]\" after \"${key}\"`,\n this.position,\n );\n }\n const operator = operatorMatch[0] as Operator;\n this.position += operator.length;\n\n const valueStart = this.position;\n const value = this.parseValue();\n if (this.source[this.position] !== ']') throw new QueryError('expected \"]\" to close the predicate', this.position);\n this.position += 1;\n // A pattern is checked here rather than where it runs, because here is the\n // only place that knows where in the selector it was written. It used to be\n // compiled on first use and an unparseable one silently matched nothing,\n // which is the same silence a misspelled relation would have produced if\n // this grammar tolerated one. See ADR-0017.\n if (operator === '~=') {\n try {\n pattern(value);\n } catch (error) {\n if (!(error instanceof PatternError)) throw error;\n throw new QueryError(error.message, valueStart + error.offset + (quoted(this.source[valueStart]) ? 1 : 0));\n }\n }\n return { key, operator, value };\n }\n\n private parseValue(): string {\n const quote = this.source[this.position];\n if (quote === '\"' || quote === \"'\") {\n this.position += 1;\n let out = '';\n while (this.position < this.source.length && this.source[this.position] !== quote) {\n if (this.source[this.position] === '\\\\') this.position += 1;\n out += this.source[this.position] ?? '';\n this.position += 1;\n }\n if (this.source[this.position] !== quote) throw new QueryError('unterminated quoted value', this.position);\n this.position += 1;\n return out;\n }\n const match = /^[^\\]\\s]*/.exec(this.source.slice(this.position));\n const value = (match?.[0] ?? '') as string;\n this.position += value.length;\n return value;\n }\n\n parseStep(): StepSpec {\n const rest = this.source.slice(this.position);\n // The forward form is lazy because its terminator is two characters (`->`),\n // which cannot be confused with the hyphen inside `delegates-to`. The\n // backward terminator is a single `-`, so it must be greedy and backtrack:\n // matching lazily would read `<-delegates-to-` as the relation `delegates`.\n const forward = /^(-|=)([A-Za-z,*-]*?)(->|=>)/.exec(rest);\n const backward = /^(<-|<=)([A-Za-z,*-]*)(-|=)(?=\\s|$|[A-Za-z*[])/.exec(rest);\n\n if (forward && (!backward || (forward.index ?? 0) <= (backward.index ?? 0))) {\n const transitive = (forward[1] as string) === '=';\n const closing = forward[3] as string;\n if ((closing === '=>') !== transitive) {\n throw new QueryError('mismatched arrow: use -kind-> for one hop or =kind=> for transitive', this.position);\n }\n const kinds = this.parseKinds(forward[2] as string, this.position + 1);\n this.position += (forward[0] as string).length;\n return { direction: 'out', kinds, transitive, node: this.parseNodeMatcher() };\n }\n\n if (backward) {\n const transitive = (backward[1] as string) === '<=';\n const closing = backward[3] as string;\n if ((closing === '=') !== transitive) {\n throw new QueryError('mismatched arrow: use <-kind- for one hop or <=kind= for transitive', this.position);\n }\n const kinds = this.parseKinds(backward[2] as string, this.position + 2);\n this.position += (backward[0] as string).length;\n return { direction: 'in', kinds, transitive, node: this.parseNodeMatcher() };\n }\n\n throw new QueryError(\n 'expected a relation step such as -delegates-to->, <-assumes- or =supersedes=>',\n this.position,\n );\n }\n\n private parseKinds(raw: string, offset: number): readonly EdgeKind[] | null {\n const trimmed = raw.trim();\n if (trimmed.length === 0 || trimmed === '*') return null;\n const kinds: EdgeKind[] = [];\n for (const part of trimmed.split(',')) {\n const name = part.trim().toLowerCase();\n if (name.length === 0) continue;\n if (!(EDGE_KINDS as readonly string[]).includes(name)) {\n throw new QueryError(`unknown relation \"${name}\", expected one of: ${EDGE_KINDS.join(', ')}`, offset);\n }\n kinds.push(name as EdgeKind);\n }\n return kinds.length > 0 ? kinds : null;\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Attributes */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Every attribute key a node can answer to, excluding the open `fm.` namespace.\n *\n * Selectors do not validate their keys - an unknown one simply matches nothing,\n * which is the forgiving reading a query typed at a prompt wants. A message\n * template is the opposite case: `{1.phse}` would render as an empty string in\n * a diagnostic somebody has to act on, silently and forever. So the list is\n * published here, next to the switch it mirrors, for the one caller that needs\n * to be strict. See ADR-0016.\n */\nexport const SELECTOR_KEYS: readonly string[] = Object.freeze([\n 'alias',\n 'body',\n 'conflicted',\n 'disposition',\n 'document',\n 'evidence',\n 'file',\n 'id',\n 'kind',\n 'line',\n 'openness',\n 'path',\n 'phase',\n 'receptivity',\n 'section',\n 'state',\n 'status',\n 'text',\n 'title',\n]);\n\n/**\n * The values a predicate key sees on a node.\n *\n * Multi-valued keys (`alias`, `section`) match when *any* value matches, which\n * is what makes `[section=Open Questions]` read the way people expect.\n */\nexport function attributesOf(node: SpecNode, key: string, graph?: SpecGraph): string[] {\n switch (key) {\n case 'id':\n return [node.id];\n case 'kind':\n return [node.kind];\n case 'title':\n return [node.title];\n case 'file':\n return [node.at.file];\n case 'line':\n return [String(node.at.span.start.line)];\n case 'document':\n return [node.kind === 'item' ? node.document : node.id];\n default:\n break;\n }\n\n if (node.kind === 'document') {\n switch (key) {\n case 'path':\n return [node.path];\n case 'phase':\n return [node.phase];\n case 'status':\n return node.rawStatus === null ? [] : [node.rawStatus];\n case 'receptivity':\n return [receptivityOf(node.phase)];\n case 'alias':\n return [...node.aliases];\n default:\n break;\n }\n if (key.startsWith('fm.')) {\n const value = node.frontMatter[key.slice(3)];\n if (value === undefined) return [];\n return typeof value === 'string' ? [value] : [...value];\n }\n return [];\n }\n\n // An item inherits its document's lifecycle. Without this, the two rules that\n // matter most could not be written as queries at all, because the question\n // they ask - \"is the document holding this obligation still open?\" - is about\n // the owner, not the item.\n if (key === 'phase' || key === 'receptivity' || key === 'status' || key === 'path' || key === 'alias') {\n const owner = graph?.owningDocument(node.id);\n if (owner) return attributesOf(owner, key, graph);\n return key === 'path' ? [node.at.file] : [];\n }\n\n switch (key) {\n case 'state':\n case 'disposition':\n return [node.disposition];\n case 'openness':\n return [node.openness];\n case 'section':\n return [...node.section];\n case 'text':\n return [node.text];\n case 'body':\n return [node.body];\n case 'evidence':\n return [node.evidence.source];\n case 'conflicted':\n return [node.conflicts.length > 0 ? 'true' : 'false'];\n default:\n return [];\n }\n}\n\nfunction testPredicate(node: SpecNode, predicate: Predicate, graph?: SpecGraph): boolean {\n const values = attributesOf(node, predicate.key, graph);\n const needle = predicate.value.toLowerCase();\n\n if (predicate.operator === 'exists') return values.some((value) => value.length > 0);\n if (predicate.operator === '!=') return !values.some((value) => value.toLowerCase() === needle);\n\n return values.some((raw) => {\n const value = raw.toLowerCase();\n switch (predicate.operator) {\n case '=':\n return value === needle;\n case '^=':\n return value.startsWith(needle);\n case '$=':\n return value.endsWith(needle);\n case '*=':\n return value.includes(needle);\n case '~=':\n return pattern(predicate.value).test(raw);\n default:\n return false;\n }\n });\n}\n\nconst patterns = new Map<string, Matcher>();\n\n/**\n * Compiles a `~=` pattern, once per distinct pattern.\n *\n * Cached because a rule runs its predicate against every node in the corpus,\n * and because compiling is the expensive half now that matching is linear.\n */\nexport function pattern(source: string): Matcher {\n const cached = patterns.get(source);\n if (cached) return cached;\n const compiled = compilePattern(source);\n patterns.set(source, compiled);\n return compiled;\n}\n\nfunction quoted(char: string | undefined): boolean {\n return char === '\"' || char === \"'\";\n}\n\n/** True when a node satisfies a matcher. */\nexport function matches(node: SpecNode, matcher: NodeMatcher, graph?: SpecGraph): boolean {\n if (matcher.kind !== null && node.kind !== matcher.kind) return false;\n return matcher.predicates.every((predicate) => testPredicate(node, predicate, graph));\n}\n\n/* -------------------------------------------------------------------------- */\n/* Execution */\n/* -------------------------------------------------------------------------- */\n\nexport interface ExecuteOptions {\n /**\n * Cap on the paths produced by each traversal step.\n *\n * It bounds *expansion*, not the initial selection: a query with no steps\n * returns every matching node. That asymmetry is deliberate. The limit exists\n * so a query across a dense graph cannot fan out unboundedly, and the rules\n * run through this engine - truncating the set of nodes a rule starts from\n * would silently drop findings, whereas truncating a runaway expansion only\n * ever drops paths that were already beyond reading.\n */\n readonly limit?: number | undefined;\n /**\n * Whether a step may stay inside one document.\n *\n * Off by default for reflexive edges: a document that links to itself is a\n * formatting quirk, not a relationship, and letting those through turns every\n * table of contents into a finding.\n */\n readonly allowReflexive?: boolean | undefined;\n}\n\n/** Runs a compiled query and returns every matching path. */\nexport function execute(graph: SpecGraph, spec: QuerySpec, options: ExecuteOptions = {}): Match[] {\n const limit = options.limit ?? DEFAULT_MATCH_LIMIT;\n const allowReflexive = options.allowReflexive ?? false;\n\n let frontier: Match[] = [];\n for (const node of graph.nodes.values()) {\n if (matches(node, spec.start, graph)) frontier.push({ nodes: [node], edges: [] });\n }\n\n for (const step of spec.steps) {\n const next: Match[] = [];\n const seen = new Set<string>();\n\n for (const match of frontier) {\n const tail = match.nodes[match.nodes.length - 1] as SpecNode;\n for (const { node, path } of expand(graph, tail, step, allowReflexive)) {\n if (!matches(node, step.node, graph)) continue;\n const key = `${match.nodes.map((n) => n.id).join('>')}>${node.id}`;\n if (seen.has(key)) continue;\n seen.add(key);\n next.push({ nodes: [...match.nodes, node], edges: [...match.edges, ...path] });\n if (next.length >= limit) break;\n }\n if (next.length >= limit) break;\n }\n\n frontier = next;\n if (frontier.length === 0) break;\n }\n\n return frontier;\n}\n\ninterface Expansion {\n readonly node: SpecNode;\n readonly path: readonly Edge[];\n}\n\nfunction expand(graph: SpecGraph, from: SpecNode, step: StepSpec, allowReflexive: boolean): Expansion[] {\n const kinds = step.kinds ?? [];\n const out: Expansion[] = [];\n\n if (!step.transitive) {\n const edges = step.direction === 'out' ? graph.out(from.id, kinds) : graph.in(from.id, kinds);\n for (const edge of edges) {\n if (!allowReflexive && edge.reflexive) continue;\n const targetId = step.direction === 'out' ? edge.to : edge.from;\n const node = graph.node(targetId);\n if (node) out.push({ node, path: [edge] });\n }\n return out;\n }\n\n // Transitive steps take the shortest path to each reachable node, which keeps\n // the result deterministic and the reported evidence minimal.\n const reached =\n step.direction === 'out'\n ? graph.reach(from.id, kinds)\n : reachIncoming(graph, from.id, kinds);\n\n for (const [id, path] of reached) {\n if (!allowReflexive && path.every((edge) => edge.reflexive)) continue;\n const node = graph.node(id);\n if (node) out.push({ node, path });\n }\n return out;\n}\n\nfunction reachIncoming(graph: SpecGraph, id: string, kinds: readonly EdgeKind[]): Map<string, readonly Edge[]> {\n const paths = new Map<string, readonly Edge[]>();\n const pathTo = new Map<string, readonly Edge[]>([[id, []]]);\n const queue: string[] = [id];\n\n while (queue.length > 0) {\n const current = queue.shift() as string;\n const prefix = pathTo.get(current) as readonly Edge[];\n for (const edge of graph.in(current, kinds)) {\n if (pathTo.has(edge.from) && edge.from !== id) continue;\n const path = [...prefix, edge];\n if (edge.from === id) {\n if (!paths.has(id)) paths.set(id, path);\n continue;\n }\n pathTo.set(edge.from, path);\n paths.set(edge.from, path);\n queue.push(edge.from);\n }\n }\n return paths;\n}\n\n/** Parses and runs a selector in one call. */\nexport function query(graph: SpecGraph, selector: string, options?: ExecuteOptions): Match[] {\n return execute(graph, parseQuery(selector), options);\n}\n\n/** Renders a match as `A -kind-> B`, for reports and for `--explain`. */\nexport function renderMatch(match: Match): string {\n const parts: string[] = [match.nodes[0]?.id ?? ''];\n for (let i = 0; i < match.edges.length; i += 1) {\n const edge = match.edges[i] as Edge;\n const node = match.nodes[i + 1];\n parts.push(`-${edge.kind}->`, node?.id ?? documentOf(edge.to));\n }\n return parts.join(' ');\n}\n"]}
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../src/select.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The selector language.\n *\n * Rules and users ask the graph the same kinds of question, so they use the same\n * machinery. Every built-in diagnostic is a path query plus a message; anything\n * a rule can find, `spec-graph query` can find too, which means a team can\n * express a convention spec-graph never anticipated without writing a plugin.\n *\n * ```text\n * item[openness=open] -delegates-to-> document[phase=retired]\n * document[phase=active] -assumes,depends-on-> document[phase=retired]\n * document =supersedes=> document[phase=active]\n * item[state=obviated] <-assumes- *\n * *[path^=docs/adr] -blocked-by-> item[openness=open]\n * ```\n *\n * A query evaluates to **paths**, not endpoints. A rule that has the whole path\n * can say \"ADR-0004 line 31 delegates this to ADR-0002, which was retired in\n * March\" instead of naming two documents and leaving the reader to reconstruct\n * the relationship.\n */\n\nimport { receptivityOf } from './lifecycle.js';\nimport { documentOf } from './resolve.js';\nimport type { SpecGraph } from './graph.js';\nimport { EDGE_KINDS, type Edge, type EdgeKind, type NodeKind, type SpecNode } from './types.js';\nimport { compileRegex, RegexError, type RegexMatcher } from './vendor/spec-core/pattern/index.js';\n\n/* -------------------------------------------------------------------------- */\n/* Shapes */\n/* -------------------------------------------------------------------------- */\n\nexport type Operator = '=' | '!=' | '^=' | '$=' | '*=' | '~=' | 'exists';\n\nexport interface Predicate {\n readonly key: string;\n readonly operator: Operator;\n readonly value: string;\n}\n\nexport interface NodeMatcher {\n /** `null` matches both documents and items. */\n readonly kind: NodeKind | null;\n readonly predicates: readonly Predicate[];\n}\n\nexport interface StepSpec {\n readonly direction: 'out' | 'in';\n /** `null` matches any edge kind. */\n readonly kinds: readonly EdgeKind[] | null;\n /** Follow the relation transitively, taking the shortest path to each node. */\n readonly transitive: boolean;\n readonly node: NodeMatcher;\n}\n\nexport interface QuerySpec {\n readonly start: NodeMatcher;\n readonly steps: readonly StepSpec[];\n}\n\n/** One path through the graph. `edges` always has one fewer entry than `nodes`. */\nexport interface Match {\n readonly nodes: readonly SpecNode[];\n readonly edges: readonly Edge[];\n}\n\nexport class QueryError extends Error {\n /** Offset into the query string where the problem starts. */\n readonly offset: number;\n\n constructor(message: string, offset: number) {\n super(message);\n this.name = 'QueryError';\n this.offset = offset;\n }\n}\n\n/** Guards against a pathological query fanning out over a huge corpus. */\nexport const DEFAULT_MATCH_LIMIT = 10_000;\n\n/* -------------------------------------------------------------------------- */\n/* Parsing */\n/* -------------------------------------------------------------------------- */\n\nconst NODE_KINDS: Readonly<Record<string, NodeKind | null>> = {\n document: 'document',\n documents: 'document',\n doc: 'document',\n docs: 'document',\n item: 'item',\n items: 'item',\n node: null,\n nodes: null,\n any: null,\n '*': null,\n};\n\n/** Compiles a selector string into a {@link QuerySpec}. */\nexport function parseQuery(source: string): QuerySpec {\n const parser = new Parser(source);\n const start = parser.parseNodeMatcher();\n const steps: StepSpec[] = [];\n parser.skipSpace();\n while (!parser.atEnd()) {\n steps.push(parser.parseStep());\n parser.skipSpace();\n }\n return { start, steps };\n}\n\nclass Parser {\n private readonly source: string;\n private position = 0;\n\n constructor(source: string) {\n this.source = source;\n }\n\n atEnd(): boolean {\n return this.position >= this.source.length;\n }\n\n skipSpace(): void {\n while (this.position < this.source.length && /\\s/.test(this.source[this.position] as string)) this.position += 1;\n }\n\n parseNodeMatcher(): NodeMatcher {\n this.skipSpace();\n let kind: NodeKind | null = null;\n const word = /^[A-Za-z]+|^\\*/.exec(this.source.slice(this.position));\n if (word) {\n const text = (word[0] as string).toLowerCase();\n if (!(text in NODE_KINDS)) {\n throw new QueryError(\n `unknown node type \"${word[0]}\", expected one of: document, item, * (any)`,\n this.position,\n );\n }\n kind = NODE_KINDS[text] as NodeKind | null;\n this.position += (word[0] as string).length;\n } else if (this.source[this.position] !== '[') {\n throw new QueryError('expected a node type (document, item or *) or a [predicate]', this.position);\n }\n\n const predicates: Predicate[] = [];\n while (this.source[this.position] === '[') predicates.push(this.parsePredicate());\n return { kind, predicates };\n }\n\n private parsePredicate(): Predicate {\n this.position += 1;\n const keyMatch = /^[A-Za-z_][A-Za-z0-9_.:-]*/.exec(this.source.slice(this.position));\n if (!keyMatch) throw new QueryError('expected an attribute name after \"[\"', this.position);\n const key = (keyMatch[0] as string).toLowerCase();\n this.position += (keyMatch[0] as string).length;\n\n if (this.source[this.position] === ']') {\n this.position += 1;\n return { key, operator: 'exists', value: '' };\n }\n\n const operatorMatch = /^(!=|\\^=|\\$=|\\*=|~=|=)/.exec(this.source.slice(this.position));\n if (!operatorMatch) {\n throw new QueryError(\n `expected an operator (=, !=, ^=, $=, *=, ~=) or \"]\" after \"${key}\"`,\n this.position,\n );\n }\n const operator = operatorMatch[0] as Operator;\n this.position += operator.length;\n\n const valueStart = this.position;\n const value = this.parseValue();\n if (this.source[this.position] !== ']') throw new QueryError('expected \"]\" to close the predicate', this.position);\n this.position += 1;\n // A pattern is checked here rather than where it runs, because here is the\n // only place that knows where in the selector it was written. It used to be\n // compiled on first use and an unparseable one silently matched nothing,\n // which is the same silence a misspelled relation would have produced if\n // this grammar tolerated one. See ADR-0017.\n if (operator === '~=') {\n try {\n pattern(value);\n } catch (error) {\n if (!(error instanceof RegexError)) throw error;\n throw new QueryError(error.message, valueStart + error.offset + (quoted(this.source[valueStart]) ? 1 : 0));\n }\n }\n return { key, operator, value };\n }\n\n private parseValue(): string {\n const quote = this.source[this.position];\n if (quote === '\"' || quote === \"'\") {\n this.position += 1;\n let out = '';\n while (this.position < this.source.length && this.source[this.position] !== quote) {\n if (this.source[this.position] === '\\\\') this.position += 1;\n out += this.source[this.position] ?? '';\n this.position += 1;\n }\n if (this.source[this.position] !== quote) throw new QueryError('unterminated quoted value', this.position);\n this.position += 1;\n return out;\n }\n const match = /^[^\\]\\s]*/.exec(this.source.slice(this.position));\n const value = (match?.[0] ?? '') as string;\n this.position += value.length;\n return value;\n }\n\n parseStep(): StepSpec {\n const rest = this.source.slice(this.position);\n // The forward form is lazy because its terminator is two characters (`->`),\n // which cannot be confused with the hyphen inside `delegates-to`. The\n // backward terminator is a single `-`, so it must be greedy and backtrack:\n // matching lazily would read `<-delegates-to-` as the relation `delegates`.\n const forward = /^(-|=)([A-Za-z,*-]*?)(->|=>)/.exec(rest);\n const backward = /^(<-|<=)([A-Za-z,*-]*)(-|=)(?=\\s|$|[A-Za-z*[])/.exec(rest);\n\n if (forward && (!backward || (forward.index ?? 0) <= (backward.index ?? 0))) {\n const transitive = (forward[1] as string) === '=';\n const closing = forward[3] as string;\n if ((closing === '=>') !== transitive) {\n throw new QueryError('mismatched arrow: use -kind-> for one hop or =kind=> for transitive', this.position);\n }\n const kinds = this.parseKinds(forward[2] as string, this.position + 1);\n this.position += (forward[0] as string).length;\n return { direction: 'out', kinds, transitive, node: this.parseNodeMatcher() };\n }\n\n if (backward) {\n const transitive = (backward[1] as string) === '<=';\n const closing = backward[3] as string;\n if ((closing === '=') !== transitive) {\n throw new QueryError('mismatched arrow: use <-kind- for one hop or <=kind= for transitive', this.position);\n }\n const kinds = this.parseKinds(backward[2] as string, this.position + 2);\n this.position += (backward[0] as string).length;\n return { direction: 'in', kinds, transitive, node: this.parseNodeMatcher() };\n }\n\n throw new QueryError(\n 'expected a relation step such as -delegates-to->, <-assumes- or =supersedes=>',\n this.position,\n );\n }\n\n private parseKinds(raw: string, offset: number): readonly EdgeKind[] | null {\n const trimmed = raw.trim();\n if (trimmed.length === 0 || trimmed === '*') return null;\n const kinds: EdgeKind[] = [];\n for (const part of trimmed.split(',')) {\n const name = part.trim().toLowerCase();\n if (name.length === 0) continue;\n if (!(EDGE_KINDS as readonly string[]).includes(name)) {\n throw new QueryError(`unknown relation \"${name}\", expected one of: ${EDGE_KINDS.join(', ')}`, offset);\n }\n kinds.push(name as EdgeKind);\n }\n return kinds.length > 0 ? kinds : null;\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Attributes */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Every attribute key a node can answer to, excluding the open `fm.` namespace.\n *\n * Selectors do not validate their keys - an unknown one simply matches nothing,\n * which is the forgiving reading a query typed at a prompt wants. A message\n * template is the opposite case: `{1.phse}` would render as an empty string in\n * a diagnostic somebody has to act on, silently and forever. So the list is\n * published here, next to the switch it mirrors, for the one caller that needs\n * to be strict. See ADR-0016.\n */\nexport const SELECTOR_KEYS: readonly string[] = Object.freeze([\n 'alias',\n 'body',\n 'conflicted',\n 'disposition',\n 'document',\n 'evidence',\n 'file',\n 'id',\n 'kind',\n 'line',\n 'openness',\n 'path',\n 'phase',\n 'receptivity',\n 'section',\n 'state',\n 'status',\n 'text',\n 'title',\n]);\n\n/**\n * The values a predicate key sees on a node.\n *\n * Multi-valued keys (`alias`, `section`) match when *any* value matches, which\n * is what makes `[section=Open Questions]` read the way people expect.\n */\nexport function attributesOf(node: SpecNode, key: string, graph?: SpecGraph): string[] {\n switch (key) {\n case 'id':\n return [node.id];\n case 'kind':\n return [node.kind];\n case 'title':\n return [node.title];\n case 'file':\n return [node.at.file];\n case 'line':\n return [String(node.at.span.start.line)];\n case 'document':\n return [node.kind === 'item' ? node.document : node.id];\n default:\n break;\n }\n\n if (node.kind === 'document') {\n switch (key) {\n case 'path':\n return [node.path];\n case 'phase':\n return [node.phase];\n case 'status':\n return node.rawStatus === null ? [] : [node.rawStatus];\n case 'receptivity':\n return [receptivityOf(node.phase)];\n case 'alias':\n return [...node.aliases];\n default:\n break;\n }\n if (key.startsWith('fm.')) {\n const value = node.frontMatter[key.slice(3)];\n if (value === undefined) return [];\n return typeof value === 'string' ? [value] : [...value];\n }\n return [];\n }\n\n // An item inherits its document's lifecycle. Without this, the two rules that\n // matter most could not be written as queries at all, because the question\n // they ask - \"is the document holding this obligation still open?\" - is about\n // the owner, not the item.\n if (key === 'phase' || key === 'receptivity' || key === 'status' || key === 'path' || key === 'alias') {\n const owner = graph?.owningDocument(node.id);\n if (owner) return attributesOf(owner, key, graph);\n return key === 'path' ? [node.at.file] : [];\n }\n\n switch (key) {\n case 'state':\n case 'disposition':\n return [node.disposition];\n case 'openness':\n return [node.openness];\n case 'section':\n return [...node.section];\n case 'text':\n return [node.text];\n case 'body':\n return [node.body];\n case 'evidence':\n return [node.evidence.source];\n case 'conflicted':\n return [node.conflicts.length > 0 ? 'true' : 'false'];\n default:\n return [];\n }\n}\n\nfunction testPredicate(node: SpecNode, predicate: Predicate, graph?: SpecGraph): boolean {\n const values = attributesOf(node, predicate.key, graph);\n const needle = predicate.value.toLowerCase();\n\n if (predicate.operator === 'exists') return values.some((value) => value.length > 0);\n if (predicate.operator === '!=') return !values.some((value) => value.toLowerCase() === needle);\n\n return values.some((raw) => {\n const value = raw.toLowerCase();\n switch (predicate.operator) {\n case '=':\n return value === needle;\n case '^=':\n return value.startsWith(needle);\n case '$=':\n return value.endsWith(needle);\n case '*=':\n return value.includes(needle);\n case '~=':\n return pattern(predicate.value).test(raw);\n default:\n return false;\n }\n });\n}\n\nconst patterns = new Map<string, RegexMatcher>();\n\n/**\n * Compiles a `~=` pattern, once per distinct pattern.\n *\n * Cached because a rule runs its predicate against every node in the corpus,\n * and because compiling is the expensive half now that matching is linear.\n */\nexport function pattern(source: string): RegexMatcher {\n const cached = patterns.get(source);\n if (cached) return cached;\n const compiled = compileRegex(source);\n patterns.set(source, compiled);\n return compiled;\n}\n\nfunction quoted(char: string | undefined): boolean {\n return char === '\"' || char === \"'\";\n}\n\n/** True when a node satisfies a matcher. */\nexport function matches(node: SpecNode, matcher: NodeMatcher, graph?: SpecGraph): boolean {\n if (matcher.kind !== null && node.kind !== matcher.kind) return false;\n return matcher.predicates.every((predicate) => testPredicate(node, predicate, graph));\n}\n\n/* -------------------------------------------------------------------------- */\n/* Execution */\n/* -------------------------------------------------------------------------- */\n\nexport interface ExecuteOptions {\n /**\n * Cap on the paths produced by each traversal step.\n *\n * It bounds *expansion*, not the initial selection: a query with no steps\n * returns every matching node. That asymmetry is deliberate. The limit exists\n * so a query across a dense graph cannot fan out unboundedly, and the rules\n * run through this engine - truncating the set of nodes a rule starts from\n * would silently drop findings, whereas truncating a runaway expansion only\n * ever drops paths that were already beyond reading.\n */\n readonly limit?: number | undefined;\n /**\n * Whether a step may stay inside one document.\n *\n * Off by default for reflexive edges: a document that links to itself is a\n * formatting quirk, not a relationship, and letting those through turns every\n * table of contents into a finding.\n */\n readonly allowReflexive?: boolean | undefined;\n}\n\n/** Runs a compiled query and returns every matching path. */\nexport function execute(graph: SpecGraph, spec: QuerySpec, options: ExecuteOptions = {}): Match[] {\n const limit = options.limit ?? DEFAULT_MATCH_LIMIT;\n const allowReflexive = options.allowReflexive ?? false;\n\n let frontier: Match[] = [];\n for (const node of graph.nodes.values()) {\n if (matches(node, spec.start, graph)) frontier.push({ nodes: [node], edges: [] });\n }\n\n for (const step of spec.steps) {\n const next: Match[] = [];\n const seen = new Set<string>();\n\n for (const match of frontier) {\n const tail = match.nodes[match.nodes.length - 1] as SpecNode;\n for (const { node, path } of expand(graph, tail, step, allowReflexive)) {\n if (!matches(node, step.node, graph)) continue;\n const key = `${match.nodes.map((n) => n.id).join('>')}>${node.id}`;\n if (seen.has(key)) continue;\n seen.add(key);\n next.push({ nodes: [...match.nodes, node], edges: [...match.edges, ...path] });\n if (next.length >= limit) break;\n }\n if (next.length >= limit) break;\n }\n\n frontier = next;\n if (frontier.length === 0) break;\n }\n\n return frontier;\n}\n\ninterface Expansion {\n readonly node: SpecNode;\n readonly path: readonly Edge[];\n}\n\nfunction expand(graph: SpecGraph, from: SpecNode, step: StepSpec, allowReflexive: boolean): Expansion[] {\n const kinds = step.kinds ?? [];\n const out: Expansion[] = [];\n\n if (!step.transitive) {\n const edges = step.direction === 'out' ? graph.out(from.id, kinds) : graph.in(from.id, kinds);\n for (const edge of edges) {\n if (!allowReflexive && edge.reflexive) continue;\n const targetId = step.direction === 'out' ? edge.to : edge.from;\n const node = graph.node(targetId);\n if (node) out.push({ node, path: [edge] });\n }\n return out;\n }\n\n // Transitive steps take the shortest path to each reachable node, which keeps\n // the result deterministic and the reported evidence minimal.\n const reached =\n step.direction === 'out'\n ? graph.reach(from.id, kinds)\n : reachIncoming(graph, from.id, kinds);\n\n for (const [id, path] of reached) {\n if (!allowReflexive && path.every((edge) => edge.reflexive)) continue;\n const node = graph.node(id);\n if (node) out.push({ node, path });\n }\n return out;\n}\n\nfunction reachIncoming(graph: SpecGraph, id: string, kinds: readonly EdgeKind[]): Map<string, readonly Edge[]> {\n const paths = new Map<string, readonly Edge[]>();\n const pathTo = new Map<string, readonly Edge[]>([[id, []]]);\n const queue: string[] = [id];\n\n while (queue.length > 0) {\n const current = queue.shift() as string;\n const prefix = pathTo.get(current) as readonly Edge[];\n for (const edge of graph.in(current, kinds)) {\n if (pathTo.has(edge.from) && edge.from !== id) continue;\n const path = [...prefix, edge];\n if (edge.from === id) {\n if (!paths.has(id)) paths.set(id, path);\n continue;\n }\n pathTo.set(edge.from, path);\n paths.set(edge.from, path);\n queue.push(edge.from);\n }\n }\n return paths;\n}\n\n/** Parses and runs a selector in one call. */\nexport function query(graph: SpecGraph, selector: string, options?: ExecuteOptions): Match[] {\n return execute(graph, parseQuery(selector), options);\n}\n\n/** Renders a match as `A -kind-> B`, for reports and for `--explain`. */\nexport function renderMatch(match: Match): string {\n const parts: string[] = [match.nodes[0]?.id ?? ''];\n for (let i = 0; i < match.edges.length; i += 1) {\n const edge = match.edges[i] as Edge;\n const node = match.nodes[i + 1];\n parts.push(`-${edge.kind}->`, node?.id ?? documentOf(edge.to));\n }\n return parts.join(' ');\n}\n"]}
package/dist/source.d.ts CHANGED
@@ -7,27 +7,14 @@
7
7
  * built once per file and searched with a binary search rather than by counting
8
8
  * newlines from the start each time.
9
9
  */
10
- import type { Position, SourceRef, Span } from './types.js';
11
- export interface LineIndex {
12
- /** Number of lines. A file ending in a newline does not gain a trailing line. */
13
- readonly lineCount: number;
14
- /** Offset at which the given 1-based line starts. */
15
- lineStart(line: number): number;
16
- /** Offset just past the given 1-based line, excluding its terminator. */
17
- lineEnd(line: number): number;
18
- /** Text of the given 1-based line, without its terminator. */
19
- lineText(line: number): string;
20
- /** Convert an absolute offset to a `{ line, column }` position. */
21
- positionAt(offset: number): Position;
22
- }
10
+ import type { LineIndex } from './vendor/spec-core/text/index.js';
11
+ import type { SourceRef, Span } from './types.js';
23
12
  /**
24
- * Builds the line table for `text`.
25
- *
26
- * Recognises all three line terminators. `\r\n` counts once: a Windows checkout
27
- * of a spec must produce the same line numbers as a POSIX one, or half the
28
- * team gets diagnostics pointing at the wrong place.
13
+ * The line table is spec-core's, which is the one this file wrote: all three
14
+ * line terminators, with CRLF counted once, so a Windows checkout of a spec
15
+ * produces the line numbers a POSIX one does.
29
16
  */
30
- export declare function createLineIndex(text: string): LineIndex;
17
+ export { createLineIndex, type LineIndex } from './vendor/spec-core/text/index.js';
31
18
  /** Builds a {@link Span} from two offsets. */
32
19
  export declare function spanOf(index: LineIndex, start: number, end: number): Span;
33
20
  /** Builds a {@link SourceRef} from two offsets. */
package/dist/source.js CHANGED
@@ -8,77 +8,11 @@
8
8
  * newlines from the start each time.
9
9
  */
10
10
  /**
11
- * Builds the line table for `text`.
12
- *
13
- * Recognises all three line terminators. `\r\n` counts once: a Windows checkout
14
- * of a spec must produce the same line numbers as a POSIX one, or half the
15
- * team gets diagnostics pointing at the wrong place.
11
+ * The line table is spec-core's, which is the one this file wrote: all three
12
+ * line terminators, with CRLF counted once, so a Windows checkout of a spec
13
+ * produces the line numbers a POSIX one does.
16
14
  */
17
- export function createLineIndex(text) {
18
- const starts = [0];
19
- for (let i = 0; i < text.length; i += 1) {
20
- const ch = text.charCodeAt(i);
21
- if (ch === 10 /* \n */) {
22
- starts.push(i + 1);
23
- }
24
- else if (ch === 13 /* \r */) {
25
- if (text.charCodeAt(i + 1) === 10)
26
- i += 1;
27
- starts.push(i + 1);
28
- }
29
- }
30
- // A terminator at the very end opens a line that contains nothing. Drop it so
31
- // `lineCount` matches what an editor shows.
32
- if (starts.length > 1 && starts[starts.length - 1] === text.length)
33
- starts.pop();
34
- const lineCount = starts.length;
35
- const startOf = (line) => {
36
- const clamped = line < 1 ? 1 : line > lineCount ? lineCount : line;
37
- return starts[clamped - 1];
38
- };
39
- const endOf = (line) => {
40
- const clamped = line < 1 ? 1 : line > lineCount ? lineCount : line;
41
- if (clamped === lineCount) {
42
- let end = text.length;
43
- while (end > starts[clamped - 1]) {
44
- const ch = text.charCodeAt(end - 1);
45
- if (ch === 10 || ch === 13)
46
- end -= 1;
47
- else
48
- break;
49
- }
50
- return end;
51
- }
52
- let end = starts[clamped];
53
- while (end > starts[clamped - 1]) {
54
- const ch = text.charCodeAt(end - 1);
55
- if (ch === 10 || ch === 13)
56
- end -= 1;
57
- else
58
- break;
59
- }
60
- return end;
61
- };
62
- return {
63
- lineCount,
64
- lineStart: startOf,
65
- lineEnd: endOf,
66
- lineText: (line) => text.slice(startOf(line), endOf(line)),
67
- positionAt(offset) {
68
- const clamped = offset < 0 ? 0 : offset > text.length ? text.length : offset;
69
- let lo = 0;
70
- let hi = starts.length - 1;
71
- while (lo < hi) {
72
- const mid = (lo + hi + 1) >> 1;
73
- if (starts[mid] <= clamped)
74
- lo = mid;
75
- else
76
- hi = mid - 1;
77
- }
78
- return { offset: clamped, line: lo + 1, column: clamped - starts[lo] + 1 };
79
- },
80
- };
81
- }
15
+ export { createLineIndex } from './vendor/spec-core/text/index.js';
82
16
  /** Builds a {@link Span} from two offsets. */
83
17
  export function spanOf(index, start, end) {
84
18
  return { start: index.positionAt(start), end: index.positionAt(end) };
@@ -1 +1 @@
1
- {"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Offset arithmetic.\n *\n * Every finding spec-graph reports points at a line and a column, and every\n * intermediate structure carries raw offsets instead of copies of the text.\n * Converting between the two is therefore on the hot path, so the line table is\n * built once per file and searched with a binary search rather than by counting\n * newlines from the start each time.\n */\n\nimport type { Position, SourceRef, Span } from './types.js';\n\nexport interface LineIndex {\n /** Number of lines. A file ending in a newline does not gain a trailing line. */\n readonly lineCount: number;\n /** Offset at which the given 1-based line starts. */\n lineStart(line: number): number;\n /** Offset just past the given 1-based line, excluding its terminator. */\n lineEnd(line: number): number;\n /** Text of the given 1-based line, without its terminator. */\n lineText(line: number): string;\n /** Convert an absolute offset to a `{ line, column }` position. */\n positionAt(offset: number): Position;\n}\n\n/**\n * Builds the line table for `text`.\n *\n * Recognises all three line terminators. `\\r\\n` counts once: a Windows checkout\n * of a spec must produce the same line numbers as a POSIX one, or half the\n * team gets diagnostics pointing at the wrong place.\n */\nexport function createLineIndex(text: string): LineIndex {\n const starts: number[] = [0];\n for (let i = 0; i < text.length; i += 1) {\n const ch = text.charCodeAt(i);\n if (ch === 10 /* \\n */) {\n starts.push(i + 1);\n } else if (ch === 13 /* \\r */) {\n if (text.charCodeAt(i + 1) === 10) i += 1;\n starts.push(i + 1);\n }\n }\n // A terminator at the very end opens a line that contains nothing. Drop it so\n // `lineCount` matches what an editor shows.\n if (starts.length > 1 && starts[starts.length - 1] === text.length) starts.pop();\n\n const lineCount = starts.length;\n\n const startOf = (line: number): number => {\n const clamped = line < 1 ? 1 : line > lineCount ? lineCount : line;\n return starts[clamped - 1] as number;\n };\n\n const endOf = (line: number): number => {\n const clamped = line < 1 ? 1 : line > lineCount ? lineCount : line;\n if (clamped === lineCount) {\n let end = text.length;\n while (end > (starts[clamped - 1] as number)) {\n const ch = text.charCodeAt(end - 1);\n if (ch === 10 || ch === 13) end -= 1;\n else break;\n }\n return end;\n }\n let end = starts[clamped] as number;\n while (end > (starts[clamped - 1] as number)) {\n const ch = text.charCodeAt(end - 1);\n if (ch === 10 || ch === 13) end -= 1;\n else break;\n }\n return end;\n };\n\n return {\n lineCount,\n lineStart: startOf,\n lineEnd: endOf,\n lineText: (line) => text.slice(startOf(line), endOf(line)),\n positionAt(offset: number): Position {\n const clamped = offset < 0 ? 0 : offset > text.length ? text.length : offset;\n let lo = 0;\n let hi = starts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if ((starts[mid] as number) <= clamped) lo = mid;\n else hi = mid - 1;\n }\n return { offset: clamped, line: lo + 1, column: clamped - (starts[lo] as number) + 1 };\n },\n };\n}\n\n/** Builds a {@link Span} from two offsets. */\nexport function spanOf(index: LineIndex, start: number, end: number): Span {\n return { start: index.positionAt(start), end: index.positionAt(end) };\n}\n\n/** Builds a {@link SourceRef} from two offsets. */\nexport function refOf(file: string, index: LineIndex, start: number, end: number): SourceRef {\n return { file, span: spanOf(index, start, end) };\n}\n\n/** `path:line:column`, the form every editor and terminal knows how to open. */\nexport function formatRef(ref: SourceRef): string {\n return `${ref.file}:${ref.span.start.line}:${ref.span.start.column}`;\n}\n\n/**\n * Sort key for deterministic report ordering.\n *\n * CI output that reorders between runs is output nobody diffs, so ordering is\n * total: file, then line, then column, then length.\n */\nexport function compareRefs(a: SourceRef, b: SourceRef): number {\n if (a.file !== b.file) return a.file < b.file ? -1 : 1;\n if (a.span.start.line !== b.span.start.line) return a.span.start.line - b.span.start.line;\n if (a.span.start.column !== b.span.start.column) return a.span.start.column - b.span.start.column;\n return a.span.end.offset - b.span.end.offset;\n}\n"]}
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;;;GAIG;AACH,OAAO,EAAE,eAAe,EAAkB,MAAM,kCAAkC,CAAC;AAEnF,8CAA8C;AAC9C,MAAM,UAAU,MAAM,CAAC,KAAgB,EAAE,KAAa,EAAE,GAAW;IACjE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,KAAgB,EAAE,KAAa,EAAE,GAAW;IAC9E,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,GAAc;IACtC,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,CAAY,EAAE,CAAY;IACpD,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC1F,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAClG,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AAC/C,CAAC","sourcesContent":["/**\n * Offset arithmetic.\n *\n * Every finding spec-graph reports points at a line and a column, and every\n * intermediate structure carries raw offsets instead of copies of the text.\n * Converting between the two is therefore on the hot path, so the line table is\n * built once per file and searched with a binary search rather than by counting\n * newlines from the start each time.\n */\n\nimport type { LineIndex } from './vendor/spec-core/text/index.js';\nimport type { SourceRef, Span } from './types.js';\n\n/**\n * The line table is spec-core's, which is the one this file wrote: all three\n * line terminators, with CRLF counted once, so a Windows checkout of a spec\n * produces the line numbers a POSIX one does.\n */\nexport { createLineIndex, type LineIndex } from './vendor/spec-core/text/index.js';\n\n/** Builds a {@link Span} from two offsets. */\nexport function spanOf(index: LineIndex, start: number, end: number): Span {\n return { start: index.positionAt(start), end: index.positionAt(end) };\n}\n\n/** Builds a {@link SourceRef} from two offsets. */\nexport function refOf(file: string, index: LineIndex, start: number, end: number): SourceRef {\n return { file, span: spanOf(index, start, end) };\n}\n\n/** `path:line:column`, the form every editor and terminal knows how to open. */\nexport function formatRef(ref: SourceRef): string {\n return `${ref.file}:${ref.span.start.line}:${ref.span.start.column}`;\n}\n\n/**\n * Sort key for deterministic report ordering.\n *\n * CI output that reorders between runs is output nobody diffs, so ordering is\n * total: file, then line, then column, then length.\n */\nexport function compareRefs(a: SourceRef, b: SourceRef): number {\n if (a.file !== b.file) return a.file < b.file ? -1 : 1;\n if (a.span.start.line !== b.span.start.line) return a.span.start.line - b.span.start.line;\n if (a.span.start.column !== b.span.start.column) return a.span.start.column - b.span.start.column;\n return a.span.end.offset - b.span.end.offset;\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * 1. **Documents have a lifecycle phase**, normalised from whatever vocabulary
7
7
  * the repository already uses (MADR `accepted`, KEP `implementable`, RFC
8
- * `final`, plain English `archived`). The phase answers one question that
8
+ * `final`, plain English `withdrawn`). The phase answers one question that
9
9
  * matters more than any other: *can this document still absorb new work?*
10
10
  *
11
11
  * 2. **Items are obligations with nuanced state.** A checkbox is not a boolean.
@@ -47,9 +47,13 @@ export interface SourceRef {
47
47
  * - `draft` - not yet binding. Mutable. Absorbs new work.
48
48
  * - `active` - binding and mutable. Absorbs new work.
49
49
  * - `frozen` - binding and immutable. Changes require a new document.
50
- * - `retired` - no longer binding: superseded, rejected, withdrawn, archived.
50
+ * - `retired` - no longer binding: superseded, rejected, withdrawn.
51
51
  *
52
- * `unknown` is a fifth, deliberately non-lattice value for documents that never
52
+ * `record` is outside the lattice: a log of what was decided, or a finished
53
+ * round of work kept as it was left (`archived`). It absorbs nothing, owes
54
+ * nothing, and is normal to depend on. See ADR-0011.
55
+ *
56
+ * `unknown` is a further, deliberately non-lattice value for documents that never
53
57
  * declared a status. Rules treat it permissively rather than guessing.
54
58
  */
55
59
  export type Phase = 'draft' | 'active' | 'frozen' | 'retired' | 'record' | 'unknown';
@@ -190,6 +194,14 @@ export interface DocumentNode extends NodeBase {
190
194
  /** Every spelling that resolves to this document, lowercased. */
191
195
  readonly aliases: readonly string[];
192
196
  readonly phase: Phase;
197
+ /**
198
+ * Declared a historical record from outside the file, by `historyPatterns`
199
+ * or `<!-- @spec-history -->`: a log, exempt from every finding about work.
200
+ * A document that reaches `record` by the status word `archived` is a closed
201
+ * round rather than a log, and answers for its supersessions, its cycles and
202
+ * its self-references still (ADR-0011).
203
+ */
204
+ readonly history: boolean;
193
205
  /** The status string as written, before normalisation. `null` if absent. */
194
206
  readonly rawStatus: string | null;
195
207
  /** Where the status was declared, when it was declared anywhere. */
@@ -342,6 +354,14 @@ export interface Diagnostic {
342
354
  export interface ParseProblem {
343
355
  readonly message: string;
344
356
  readonly at: SourceRef;
357
+ /**
358
+ * Front matter held something the graph is built from - a status, an id, an
359
+ * alias or a relation, or the whole block - and it was not read. Problems
360
+ * are listed under `--verbose`, and these are counted without it: a status
361
+ * left out reads as unknown, which can turn a failing check into a passing
362
+ * one.
363
+ */
364
+ readonly unread?: boolean | undefined;
345
365
  }
346
366
  export interface AnalysisSummary {
347
367
  readonly documents: number;
package/dist/types.js CHANGED
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * 1. **Documents have a lifecycle phase**, normalised from whatever vocabulary
7
7
  * the repository already uses (MADR `accepted`, KEP `implementable`, RFC
8
- * `final`, plain English `archived`). The phase answers one question that
8
+ * `final`, plain English `withdrawn`). The phase answers one question that
9
9
  * matters more than any other: *can this document still absorb new work?*
10
10
  *
11
11
  * 2. **Items are obligations with nuanced state.** A checkbox is not a boolean.
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA4FH,MAAM,CAAC,MAAM,YAAY,GAA2B,MAAM,CAAC,MAAM,CAAC;IAChE,YAAY;IACZ,UAAU;IACV,WAAW;IACX,WAAW;IACX,eAAe;IACf,UAAU;IACV,UAAU;CACX,CAAC,CAAC;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,WAAW,GAA4C,MAAM,CAAC,MAAM,CAAC;IAChF,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,QAAQ;IACnB,eAAe,EAAE,QAAQ;IACzB,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,QAAQ;CACnB,CAAC,CAAC;AAkDH,MAAM,CAAC,MAAM,WAAW,GAA2C,MAAM,CAAC,MAAM,CAAC;IAC/E,QAAQ,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE;IAClG,UAAU,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE;IACtG,YAAY,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE;IACxG,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE;IACvG,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE;IAC/F,cAAc,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE;IAC3G,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE;IACzG,UAAU,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE;IACrG,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;CAC7F,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAwB,CAAC;AAqN1E,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,IAAe;IAC3C,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC","sourcesContent":["/**\n * The spec-graph data model.\n *\n * Three ideas carry the whole design:\n *\n * 1. **Documents have a lifecycle phase**, normalised from whatever vocabulary\n * the repository already uses (MADR `accepted`, KEP `implementable`, RFC\n * `final`, plain English `archived`). The phase answers one question that\n * matters more than any other: *can this document still absorb new work?*\n *\n * 2. **Items are obligations with nuanced state.** A checkbox is not a boolean.\n * An item can be open, narrowed to a smaller scope, satisfied, consciously\n * accepted as debt, or obviated because the premise it rested on evaporated.\n * Collapsing those five into `[ ]` / `[x]` is what makes ad-hoc greps lie.\n *\n * 3. **Edges are typed and carry provenance.** Every relation records where it\n * was *declared*, which is frequently not the node it points at. That is what\n * lets a diagnostic say \"ADR-0009 line 12 claims to supersede ADR-0003\"\n * instead of \"something, somewhere, is inconsistent\".\n */\n\n/* -------------------------------------------------------------------------- */\n/* Source positions */\n/* -------------------------------------------------------------------------- */\n\n/** A point in a source file. `offset` is a UTF-16 code-unit index. */\nexport interface Position {\n readonly offset: number;\n /** 1-based. */\n readonly line: number;\n /** 1-based, counted in UTF-16 code units. */\n readonly column: number;\n}\n\n/** A half-open `[start, end)` range of a source file. */\nexport interface Span {\n readonly start: Position;\n readonly end: Position;\n}\n\n/** A span plus the file it belongs to. Everything user-visible carries one. */\nexport interface SourceRef {\n /** Repository-relative POSIX path. */\n readonly file: string;\n readonly span: Span;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Lifecycle */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The normalised document lifecycle, as a four-state lattice.\n *\n * Ecosystem vocabularies are large and mutually incompatible; the *consequences*\n * of a status are not. These four phases are chosen so that every question\n * spec-graph asks can be answered from the phase alone.\n *\n * - `draft` - not yet binding. Mutable. Absorbs new work.\n * - `active` - binding and mutable. Absorbs new work.\n * - `frozen` - binding and immutable. Changes require a new document.\n * - `retired` - no longer binding: superseded, rejected, withdrawn, archived.\n *\n * `unknown` is a fifth, deliberately non-lattice value for documents that never\n * declared a status. Rules treat it permissively rather than guessing.\n */\nexport type Phase = 'draft' | 'active' | 'frozen' | 'retired' | 'record' | 'unknown';\n\n/**\n * Can a document in this phase take on a *new* open obligation?\n *\n * This is the single predicate behind ghost-handover detection. Delegating an\n * open question into a `frozen` or `retired` document is a write to a closed\n * ledger: nobody will ever read it again.\n */\nexport type Receptivity = 'receptive' | 'sealed' | 'unknown';\n\n/* -------------------------------------------------------------------------- */\n/* Item state */\n/* -------------------------------------------------------------------------- */\n\n/**\n * How much of an obligation is left.\n *\n * Kept separate from {@link Disposition} because the two answer different\n * questions: `openness` is \"does someone still owe work?\", `disposition` is\n * \"what happened to it?\". Rules almost always want the former; humans reading a\n * report always want the latter.\n */\nexport type Openness = 'open' | 'partial' | 'closed';\n\n/** Why an item is in the state it is in. */\nexport type Disposition =\n /** Nothing has happened yet. */\n | 'unresolved'\n /** Scope was cut down, but a remainder is still owed. */\n | 'narrowed'\n /** Ownership moved elsewhere. Still owed - by somebody else. */\n | 'delegated'\n /** Done, answered, decided. */\n | 'satisfied'\n /** Knowingly not done. A closed item with a scar. */\n | 'accepted-debt'\n /** Decided against. */\n | 'rejected'\n /**\n * The premise evaporated, so the question stopped being a question.\n * Load-bearing citations to an obviated item are stale premises.\n */\n | 'obviated';\n\nexport const DISPOSITIONS: readonly Disposition[] = Object.freeze([\n 'unresolved',\n 'narrowed',\n 'delegated',\n 'satisfied',\n 'accepted-debt',\n 'rejected',\n 'obviated',\n]);\n\n/** The openness implied by each disposition. */\nexport const OPENNESS_OF: Readonly<Record<Disposition, Openness>> = Object.freeze({\n unresolved: 'open',\n narrowed: 'partial',\n delegated: 'open',\n satisfied: 'closed',\n 'accepted-debt': 'closed',\n rejected: 'closed',\n obviated: 'closed',\n});\n\n/* -------------------------------------------------------------------------- */\n/* Edges */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Relation kinds.\n *\n * The set is small on purpose. Two orthogonal properties - declared once in\n * {@link EDGE_TRAITS} - do the actual work, so adding a kind never means\n * touching a rule.\n */\nexport type EdgeKind =\n /** Structural: a document contains an item. Never inferred from prose. */\n | 'contains'\n /** A neutral citation. */\n | 'references'\n /** Explicitly *not* load-bearing: \"See also\", \"History\", \"Prior art\". */\n | 'relates-to'\n /** The source design depends on the target content. */\n | 'depends-on'\n /** The source rests on a claim made by the target. */\n | 'assumes'\n /** The source hands an obligation to the target. */\n | 'delegates-to'\n /** The source cannot proceed until the target does. */\n | 'blocked-by'\n /** The source replaces the target. */\n | 'supersedes'\n /** The source modifies the target without replacing it. */\n | 'amends';\n\nexport interface EdgeTraits {\n /**\n * Does the source continued validity depend on what the target says?\n *\n * Load-bearing edges into retired documents are stale premises. Non\n * load-bearing ones (\"see also\") are just history, and reporting them would\n * bury the real findings - which is exactly how ad-hoc linters lose trust.\n */\n readonly loadBearing: boolean;\n /** Does the edge move an obligation from source to target? */\n readonly transfersObligation: boolean;\n /** Does the edge assert something about the target lifecycle? */\n readonly lifecycle: boolean;\n /** Human-readable phrase used in diagnostics: \"ADR-1 <phrase> ADR-2\". */\n readonly phrase: string;\n}\n\nexport const EDGE_TRAITS: Readonly<Record<EdgeKind, EdgeTraits>> = Object.freeze({\n contains: { loadBearing: false, transfersObligation: false, lifecycle: false, phrase: 'contains' },\n references: { loadBearing: false, transfersObligation: false, lifecycle: false, phrase: 'references' },\n 'relates-to': { loadBearing: false, transfersObligation: false, lifecycle: false, phrase: 'relates to' },\n 'depends-on': { loadBearing: true, transfersObligation: false, lifecycle: false, phrase: 'depends on' },\n assumes: { loadBearing: true, transfersObligation: false, lifecycle: false, phrase: 'assumes' },\n 'delegates-to': { loadBearing: false, transfersObligation: true, lifecycle: false, phrase: 'delegates to' },\n 'blocked-by': { loadBearing: true, transfersObligation: true, lifecycle: false, phrase: 'is blocked by' },\n supersedes: { loadBearing: false, transfersObligation: false, lifecycle: true, phrase: 'supersedes' },\n amends: { loadBearing: true, transfersObligation: false, lifecycle: true, phrase: 'amends' },\n});\n\nexport const EDGE_KINDS = Object.keys(EDGE_TRAITS) as readonly EdgeKind[];\n\n/** How an edge came to exist. Reported verbatim so findings are auditable. */\nexport type EdgeOrigin =\n /** A `<!-- @spec-edge -->` directive. */\n | 'directive'\n /** A front-matter field such as `supersedes:` or `superseded-by:`. */\n | 'front-matter'\n /** A Markdown link, classified by the section it sits in. */\n | 'link'\n /** A bare textual identifier such as `ADR-0007` in prose. */\n | 'text'\n /** Synthesised by the extractor (document -> item). */\n | 'structural';\n\nexport interface Edge {\n readonly kind: EdgeKind;\n /** Node id. */\n readonly from: string;\n /** Node id. */\n readonly to: string;\n readonly origin: EdgeOrigin;\n /**\n * Where the relation was written down. Not necessarily inside `from`: a\n * `superseded-by: ADR-9` field in ADR-3 declares `ADR-9 supersedes ADR-3`,\n * and the only place a human can go fix it is ADR-3.\n */\n readonly declaredAt: SourceRef;\n /** The raw text that produced the edge, for diagnostics. */\n readonly raw: string;\n /**\n * Every file that declares this relation.\n *\n * A supersession stated only in the superseding document leaves the\n * superseded one silently presenting itself as current, which is a finding in\n * its own right - so the set of declaration sites has to survive de-duplication.\n */\n readonly declaredIn: readonly string[];\n /** True when `from` and `to` are the same node. Kept, never traversed. */\n readonly reflexive: boolean;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Nodes */\n/* -------------------------------------------------------------------------- */\n\nexport type NodeKind = 'document' | 'item';\n\ninterface NodeBase {\n /** Canonical, graph-unique. Documents: `ADR-0007`. Items: `ADR-0007#q.1`. */\n readonly id: string;\n readonly kind: NodeKind;\n /** Short human label used in reports. */\n readonly title: string;\n readonly at: SourceRef;\n}\n\nexport interface DocumentNode extends NodeBase {\n readonly kind: 'document';\n /** Repository-relative POSIX path. */\n readonly path: string;\n /** Every spelling that resolves to this document, lowercased. */\n readonly aliases: readonly string[];\n readonly phase: Phase;\n /** The status string as written, before normalisation. `null` if absent. */\n readonly rawStatus: string | null;\n /** Where the status was declared, when it was declared anywhere. */\n readonly statusAt: SourceRef | null;\n /** Front-matter fields, flattened to strings and string arrays. */\n readonly frontMatter: Readonly<Record<string, string | readonly string[]>>;\n}\n\nexport interface ItemNode extends NodeBase {\n readonly kind: 'item';\n /**\n * Whether the id was written by an author rather than numbered by position.\n *\n * A numbered id is the item's ordinal within its section, so inserting one\n * item renumbers every item after it. Only a declared id names the same item\n * in two states of a repository (ADR-0020).\n */\n readonly declared: boolean;\n /** Owning document id. */\n readonly document: string;\n /** Heading path the item sits under, outermost first. */\n readonly section: readonly string[];\n /** First line of the item, normalised to one line for reports. */\n readonly text: string;\n /** The full multi-line body, continuations included. */\n readonly body: string;\n readonly disposition: Disposition;\n readonly openness: Openness;\n /** Which signal decided the disposition. */\n readonly evidence: StateSignal;\n /** Conflicting signals found while resolving the state. */\n readonly conflicts: readonly StateSignal[];\n}\n\nexport type SpecNode = DocumentNode | ItemNode;\n\n/** One observation about an item state. */\nexport interface StateSignal {\n /** Higher wins. See `SIGNAL_PRIORITY` in `state.ts`. */\n readonly source: 'directive' | 'marker' | 'strikethrough' | 'checkbox' | 'section' | 'default';\n readonly disposition: Disposition;\n /** The literal text that produced the signal. */\n readonly raw: string;\n readonly at: SourceRef;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Unresolved references */\n/* -------------------------------------------------------------------------- */\n\nexport type DanglingReason =\n /** Nothing in the corpus answers to this identifier. */\n | 'unknown-target'\n /** More than one document answers to it. */\n | 'ambiguous'\n /** The path exists on disk but is not a parsed specification. */\n | 'not-a-spec'\n /** The document resolved, but the `#anchor` did not. */\n | 'unknown-anchor';\n\n/** A citation that failed foreign-key validation. */\nexport interface DanglingRef {\n readonly kind: EdgeKind;\n readonly from: string;\n /** The identifier as written. */\n readonly target: string;\n readonly reason: DanglingReason;\n readonly origin: EdgeOrigin;\n readonly declaredAt: SourceRef;\n readonly raw: string;\n /** Candidate ids when `reason` is `ambiguous`, or near-misses otherwise. */\n readonly candidates: readonly string[];\n}\n\n/**\n * A citation that failed to resolve and that configuration told us to ignore.\n *\n * Kept so a repository can audit its own silence. `ignoreReferences` and\n * `ignoreFamilies` are the two places a team can tell spec-graph to stop\n * reporting something, and a single over-broad glob can quietly turn the whole\n * check off - which looks exactly like a clean repository. The opportunistic\n * rule from [ADR-0004] is deliberately not counted here: reading `SHA-256` as\n * prose is spec-graph's own judgement, not a decision anybody wrote down, and\n * listing it would bury the handful of entries that are. See ADR-0008.\n */\nexport interface SuppressedRef {\n /** The identifier as written. */\n readonly target: string;\n /** The document that wrote it. */\n readonly from: string;\n readonly at: SourceRef;\n /** Which declaration silenced it. */\n readonly by: 'reference' | 'family';\n}\n\n/**\n * A front-matter key that reads as a relation and is not one.\n *\n * Front matter is an open vocabulary - `title`, `tags`, `sidebar_position` and\n * whatever else the site generator wants all live there - so an unrecognised key\n * is normally none of spec-graph's business. This is the exception: a key one\n * character away from a relation, carrying something shaped like a citation, is\n * a relation the author believes they declared. The edge does not exist, and\n * nothing else would ever say so.\n */\nexport interface MisreadKey {\n /** The key as written. */\n readonly key: string;\n /** The relation key it is a hair away from. */\n readonly suggestion: string;\n /** The document the key was written in. */\n readonly from: string;\n readonly at: SourceRef;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Diagnostics */\n/* -------------------------------------------------------------------------- */\n\nexport type Severity = 'error' | 'warn' | 'info' | 'off';\n\nexport type RuleId =\n | 'ghost-handover'\n | 'stale-premise'\n | 'broken-reference'\n | 'reference-outside-corpus'\n | 'ambiguous-reference'\n | 'circular-delegation'\n | 'orphaned-obligation'\n | 'unreciprocated-supersession'\n | 'live-supersession'\n | 'state-conflict'\n | 'self-reference'\n | 'unknown-relation-key';\n\n/**\n * A rule a repository wrote for itself, as a selector plus a sentence.\n *\n * Namespaced, and the namespace is load-bearing rather than decorative. A\n * built-in id can never contain a colon, so a project rule can never collide\n * with one however it is named - which means `--rule`, the severity table, a\n * baseline entry and a SARIF `ruleId` all keep working without anyone having to\n * reserve a vocabulary. See ADR-0016.\n */\nexport type ProjectRuleId = `project:${string}`;\n\n/** Any rule that can produce a finding: built in, or written by a repository. */\nexport type AnyRuleId = RuleId | ProjectRuleId;\n\n/** True for an id in the project namespace, as opposed to a built-in. */\nexport function isProjectRule(rule: AnyRuleId): rule is ProjectRuleId {\n return rule.startsWith(PROJECT_RULE_PREFIX);\n}\n\nexport const PROJECT_RULE_PREFIX = 'project:';\n\nexport interface RelatedLocation {\n readonly at: SourceRef;\n readonly note: string;\n}\n\nexport interface Diagnostic {\n readonly rule: AnyRuleId;\n readonly severity: Exclude<Severity, 'off'>;\n /** One line, no trailing period. The headline of the finding. */\n readonly message: string;\n /** Where a human should go to fix it. */\n readonly at: SourceRef;\n /** Node ids involved, most relevant first. */\n readonly nodes: readonly string[];\n /**\n * What within the document this finding is about, where that is not a node.\n *\n * `null` everywhere else, where `nodes` already names the subject. It exists\n * because a broken reference names something that is not a node - that is\n * what makes it broken - and a baseline still has to be able to tell one\n * broken reference from another. A misread front-matter key is the same\n * shape: a spelling, not a node. See ADR-0012.\n */\n readonly target: string | null;\n /** Supporting locations: the other end of an edge, a cycle members. */\n readonly related: readonly RelatedLocation[];\n /** Concrete next action. */\n readonly hint: string;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Analysis output */\n/* -------------------------------------------------------------------------- */\n\n/** A problem with the input itself, as opposed to a finding about the graph. */\nexport interface ParseProblem {\n readonly message: string;\n readonly at: SourceRef;\n}\n\nexport interface AnalysisSummary {\n readonly documents: number;\n readonly items: number;\n readonly edges: number;\n readonly openObligations: number;\n readonly errors: number;\n readonly warnings: number;\n readonly infos: number;\n /** Milliseconds, wall clock. */\n readonly durationMs: number;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAgGH,MAAM,CAAC,MAAM,YAAY,GAA2B,MAAM,CAAC,MAAM,CAAC;IAChE,YAAY;IACZ,UAAU;IACV,WAAW;IACX,WAAW;IACX,eAAe;IACf,UAAU;IACV,UAAU;CACX,CAAC,CAAC;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,WAAW,GAA4C,MAAM,CAAC,MAAM,CAAC;IAChF,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,QAAQ;IACnB,eAAe,EAAE,QAAQ;IACzB,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,QAAQ;CACnB,CAAC,CAAC;AAkDH,MAAM,CAAC,MAAM,WAAW,GAA2C,MAAM,CAAC,MAAM,CAAC;IAC/E,QAAQ,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE;IAClG,UAAU,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE;IACtG,YAAY,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE;IACxG,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE;IACvG,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE;IAC/F,cAAc,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE;IAC3G,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE;IACzG,UAAU,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE;IACrG,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;CAC7F,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAwB,CAAC;AA6N1E,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,IAAe;IAC3C,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC","sourcesContent":["/**\n * The spec-graph data model.\n *\n * Three ideas carry the whole design:\n *\n * 1. **Documents have a lifecycle phase**, normalised from whatever vocabulary\n * the repository already uses (MADR `accepted`, KEP `implementable`, RFC\n * `final`, plain English `withdrawn`). The phase answers one question that\n * matters more than any other: *can this document still absorb new work?*\n *\n * 2. **Items are obligations with nuanced state.** A checkbox is not a boolean.\n * An item can be open, narrowed to a smaller scope, satisfied, consciously\n * accepted as debt, or obviated because the premise it rested on evaporated.\n * Collapsing those five into `[ ]` / `[x]` is what makes ad-hoc greps lie.\n *\n * 3. **Edges are typed and carry provenance.** Every relation records where it\n * was *declared*, which is frequently not the node it points at. That is what\n * lets a diagnostic say \"ADR-0009 line 12 claims to supersede ADR-0003\"\n * instead of \"something, somewhere, is inconsistent\".\n */\n\n/* -------------------------------------------------------------------------- */\n/* Source positions */\n/* -------------------------------------------------------------------------- */\n\n/** A point in a source file. `offset` is a UTF-16 code-unit index. */\nexport interface Position {\n readonly offset: number;\n /** 1-based. */\n readonly line: number;\n /** 1-based, counted in UTF-16 code units. */\n readonly column: number;\n}\n\n/** A half-open `[start, end)` range of a source file. */\nexport interface Span {\n readonly start: Position;\n readonly end: Position;\n}\n\n/** A span plus the file it belongs to. Everything user-visible carries one. */\nexport interface SourceRef {\n /** Repository-relative POSIX path. */\n readonly file: string;\n readonly span: Span;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Lifecycle */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The normalised document lifecycle, as a four-state lattice.\n *\n * Ecosystem vocabularies are large and mutually incompatible; the *consequences*\n * of a status are not. These four phases are chosen so that every question\n * spec-graph asks can be answered from the phase alone.\n *\n * - `draft` - not yet binding. Mutable. Absorbs new work.\n * - `active` - binding and mutable. Absorbs new work.\n * - `frozen` - binding and immutable. Changes require a new document.\n * - `retired` - no longer binding: superseded, rejected, withdrawn.\n *\n * `record` is outside the lattice: a log of what was decided, or a finished\n * round of work kept as it was left (`archived`). It absorbs nothing, owes\n * nothing, and is normal to depend on. See ADR-0011.\n *\n * `unknown` is a further, deliberately non-lattice value for documents that never\n * declared a status. Rules treat it permissively rather than guessing.\n */\nexport type Phase = 'draft' | 'active' | 'frozen' | 'retired' | 'record' | 'unknown';\n\n/**\n * Can a document in this phase take on a *new* open obligation?\n *\n * This is the single predicate behind ghost-handover detection. Delegating an\n * open question into a `frozen` or `retired` document is a write to a closed\n * ledger: nobody will ever read it again.\n */\nexport type Receptivity = 'receptive' | 'sealed' | 'unknown';\n\n/* -------------------------------------------------------------------------- */\n/* Item state */\n/* -------------------------------------------------------------------------- */\n\n/**\n * How much of an obligation is left.\n *\n * Kept separate from {@link Disposition} because the two answer different\n * questions: `openness` is \"does someone still owe work?\", `disposition` is\n * \"what happened to it?\". Rules almost always want the former; humans reading a\n * report always want the latter.\n */\nexport type Openness = 'open' | 'partial' | 'closed';\n\n/** Why an item is in the state it is in. */\nexport type Disposition =\n /** Nothing has happened yet. */\n | 'unresolved'\n /** Scope was cut down, but a remainder is still owed. */\n | 'narrowed'\n /** Ownership moved elsewhere. Still owed - by somebody else. */\n | 'delegated'\n /** Done, answered, decided. */\n | 'satisfied'\n /** Knowingly not done. A closed item with a scar. */\n | 'accepted-debt'\n /** Decided against. */\n | 'rejected'\n /**\n * The premise evaporated, so the question stopped being a question.\n * Load-bearing citations to an obviated item are stale premises.\n */\n | 'obviated';\n\nexport const DISPOSITIONS: readonly Disposition[] = Object.freeze([\n 'unresolved',\n 'narrowed',\n 'delegated',\n 'satisfied',\n 'accepted-debt',\n 'rejected',\n 'obviated',\n]);\n\n/** The openness implied by each disposition. */\nexport const OPENNESS_OF: Readonly<Record<Disposition, Openness>> = Object.freeze({\n unresolved: 'open',\n narrowed: 'partial',\n delegated: 'open',\n satisfied: 'closed',\n 'accepted-debt': 'closed',\n rejected: 'closed',\n obviated: 'closed',\n});\n\n/* -------------------------------------------------------------------------- */\n/* Edges */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Relation kinds.\n *\n * The set is small on purpose. Two orthogonal properties - declared once in\n * {@link EDGE_TRAITS} - do the actual work, so adding a kind never means\n * touching a rule.\n */\nexport type EdgeKind =\n /** Structural: a document contains an item. Never inferred from prose. */\n | 'contains'\n /** A neutral citation. */\n | 'references'\n /** Explicitly *not* load-bearing: \"See also\", \"History\", \"Prior art\". */\n | 'relates-to'\n /** The source design depends on the target content. */\n | 'depends-on'\n /** The source rests on a claim made by the target. */\n | 'assumes'\n /** The source hands an obligation to the target. */\n | 'delegates-to'\n /** The source cannot proceed until the target does. */\n | 'blocked-by'\n /** The source replaces the target. */\n | 'supersedes'\n /** The source modifies the target without replacing it. */\n | 'amends';\n\nexport interface EdgeTraits {\n /**\n * Does the source continued validity depend on what the target says?\n *\n * Load-bearing edges into retired documents are stale premises. Non\n * load-bearing ones (\"see also\") are just history, and reporting them would\n * bury the real findings - which is exactly how ad-hoc linters lose trust.\n */\n readonly loadBearing: boolean;\n /** Does the edge move an obligation from source to target? */\n readonly transfersObligation: boolean;\n /** Does the edge assert something about the target lifecycle? */\n readonly lifecycle: boolean;\n /** Human-readable phrase used in diagnostics: \"ADR-1 <phrase> ADR-2\". */\n readonly phrase: string;\n}\n\nexport const EDGE_TRAITS: Readonly<Record<EdgeKind, EdgeTraits>> = Object.freeze({\n contains: { loadBearing: false, transfersObligation: false, lifecycle: false, phrase: 'contains' },\n references: { loadBearing: false, transfersObligation: false, lifecycle: false, phrase: 'references' },\n 'relates-to': { loadBearing: false, transfersObligation: false, lifecycle: false, phrase: 'relates to' },\n 'depends-on': { loadBearing: true, transfersObligation: false, lifecycle: false, phrase: 'depends on' },\n assumes: { loadBearing: true, transfersObligation: false, lifecycle: false, phrase: 'assumes' },\n 'delegates-to': { loadBearing: false, transfersObligation: true, lifecycle: false, phrase: 'delegates to' },\n 'blocked-by': { loadBearing: true, transfersObligation: true, lifecycle: false, phrase: 'is blocked by' },\n supersedes: { loadBearing: false, transfersObligation: false, lifecycle: true, phrase: 'supersedes' },\n amends: { loadBearing: true, transfersObligation: false, lifecycle: true, phrase: 'amends' },\n});\n\nexport const EDGE_KINDS = Object.keys(EDGE_TRAITS) as readonly EdgeKind[];\n\n/** How an edge came to exist. Reported verbatim so findings are auditable. */\nexport type EdgeOrigin =\n /** A `<!-- @spec-edge -->` directive. */\n | 'directive'\n /** A front-matter field such as `supersedes:` or `superseded-by:`. */\n | 'front-matter'\n /** A Markdown link, classified by the section it sits in. */\n | 'link'\n /** A bare textual identifier such as `ADR-0007` in prose. */\n | 'text'\n /** Synthesised by the extractor (document -> item). */\n | 'structural';\n\nexport interface Edge {\n readonly kind: EdgeKind;\n /** Node id. */\n readonly from: string;\n /** Node id. */\n readonly to: string;\n readonly origin: EdgeOrigin;\n /**\n * Where the relation was written down. Not necessarily inside `from`: a\n * `superseded-by: ADR-9` field in ADR-3 declares `ADR-9 supersedes ADR-3`,\n * and the only place a human can go fix it is ADR-3.\n */\n readonly declaredAt: SourceRef;\n /** The raw text that produced the edge, for diagnostics. */\n readonly raw: string;\n /**\n * Every file that declares this relation.\n *\n * A supersession stated only in the superseding document leaves the\n * superseded one silently presenting itself as current, which is a finding in\n * its own right - so the set of declaration sites has to survive de-duplication.\n */\n readonly declaredIn: readonly string[];\n /** True when `from` and `to` are the same node. Kept, never traversed. */\n readonly reflexive: boolean;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Nodes */\n/* -------------------------------------------------------------------------- */\n\nexport type NodeKind = 'document' | 'item';\n\ninterface NodeBase {\n /** Canonical, graph-unique. Documents: `ADR-0007`. Items: `ADR-0007#q.1`. */\n readonly id: string;\n readonly kind: NodeKind;\n /** Short human label used in reports. */\n readonly title: string;\n readonly at: SourceRef;\n}\n\nexport interface DocumentNode extends NodeBase {\n readonly kind: 'document';\n /** Repository-relative POSIX path. */\n readonly path: string;\n /** Every spelling that resolves to this document, lowercased. */\n readonly aliases: readonly string[];\n readonly phase: Phase;\n /**\n * Declared a historical record from outside the file, by `historyPatterns`\n * or `<!-- @spec-history -->`: a log, exempt from every finding about work.\n * A document that reaches `record` by the status word `archived` is a closed\n * round rather than a log, and answers for its supersessions, its cycles and\n * its self-references still (ADR-0011).\n */\n readonly history: boolean;\n /** The status string as written, before normalisation. `null` if absent. */\n readonly rawStatus: string | null;\n /** Where the status was declared, when it was declared anywhere. */\n readonly statusAt: SourceRef | null;\n /** Front-matter fields, flattened to strings and string arrays. */\n readonly frontMatter: Readonly<Record<string, string | readonly string[]>>;\n}\n\nexport interface ItemNode extends NodeBase {\n readonly kind: 'item';\n /**\n * Whether the id was written by an author rather than numbered by position.\n *\n * A numbered id is the item's ordinal within its section, so inserting one\n * item renumbers every item after it. Only a declared id names the same item\n * in two states of a repository (ADR-0020).\n */\n readonly declared: boolean;\n /** Owning document id. */\n readonly document: string;\n /** Heading path the item sits under, outermost first. */\n readonly section: readonly string[];\n /** First line of the item, normalised to one line for reports. */\n readonly text: string;\n /** The full multi-line body, continuations included. */\n readonly body: string;\n readonly disposition: Disposition;\n readonly openness: Openness;\n /** Which signal decided the disposition. */\n readonly evidence: StateSignal;\n /** Conflicting signals found while resolving the state. */\n readonly conflicts: readonly StateSignal[];\n}\n\nexport type SpecNode = DocumentNode | ItemNode;\n\n/** One observation about an item state. */\nexport interface StateSignal {\n /** Higher wins. See `SIGNAL_PRIORITY` in `state.ts`. */\n readonly source: 'directive' | 'marker' | 'strikethrough' | 'checkbox' | 'section' | 'default';\n readonly disposition: Disposition;\n /** The literal text that produced the signal. */\n readonly raw: string;\n readonly at: SourceRef;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Unresolved references */\n/* -------------------------------------------------------------------------- */\n\nexport type DanglingReason =\n /** Nothing in the corpus answers to this identifier. */\n | 'unknown-target'\n /** More than one document answers to it. */\n | 'ambiguous'\n /** The path exists on disk but is not a parsed specification. */\n | 'not-a-spec'\n /** The document resolved, but the `#anchor` did not. */\n | 'unknown-anchor';\n\n/** A citation that failed foreign-key validation. */\nexport interface DanglingRef {\n readonly kind: EdgeKind;\n readonly from: string;\n /** The identifier as written. */\n readonly target: string;\n readonly reason: DanglingReason;\n readonly origin: EdgeOrigin;\n readonly declaredAt: SourceRef;\n readonly raw: string;\n /** Candidate ids when `reason` is `ambiguous`, or near-misses otherwise. */\n readonly candidates: readonly string[];\n}\n\n/**\n * A citation that failed to resolve and that configuration told us to ignore.\n *\n * Kept so a repository can audit its own silence. `ignoreReferences` and\n * `ignoreFamilies` are the two places a team can tell spec-graph to stop\n * reporting something, and a single over-broad glob can quietly turn the whole\n * check off - which looks exactly like a clean repository. The opportunistic\n * rule from [ADR-0004] is deliberately not counted here: reading `SHA-256` as\n * prose is spec-graph's own judgement, not a decision anybody wrote down, and\n * listing it would bury the handful of entries that are. See ADR-0008.\n */\nexport interface SuppressedRef {\n /** The identifier as written. */\n readonly target: string;\n /** The document that wrote it. */\n readonly from: string;\n readonly at: SourceRef;\n /** Which declaration silenced it. */\n readonly by: 'reference' | 'family';\n}\n\n/**\n * A front-matter key that reads as a relation and is not one.\n *\n * Front matter is an open vocabulary - `title`, `tags`, `sidebar_position` and\n * whatever else the site generator wants all live there - so an unrecognised key\n * is normally none of spec-graph's business. This is the exception: a key one\n * character away from a relation, carrying something shaped like a citation, is\n * a relation the author believes they declared. The edge does not exist, and\n * nothing else would ever say so.\n */\nexport interface MisreadKey {\n /** The key as written. */\n readonly key: string;\n /** The relation key it is a hair away from. */\n readonly suggestion: string;\n /** The document the key was written in. */\n readonly from: string;\n readonly at: SourceRef;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Diagnostics */\n/* -------------------------------------------------------------------------- */\n\nexport type Severity = 'error' | 'warn' | 'info' | 'off';\n\nexport type RuleId =\n | 'ghost-handover'\n | 'stale-premise'\n | 'broken-reference'\n | 'reference-outside-corpus'\n | 'ambiguous-reference'\n | 'circular-delegation'\n | 'orphaned-obligation'\n | 'unreciprocated-supersession'\n | 'live-supersession'\n | 'state-conflict'\n | 'self-reference'\n | 'unknown-relation-key';\n\n/**\n * A rule a repository wrote for itself, as a selector plus a sentence.\n *\n * Namespaced, and the namespace is load-bearing rather than decorative. A\n * built-in id can never contain a colon, so a project rule can never collide\n * with one however it is named - which means `--rule`, the severity table, a\n * baseline entry and a SARIF `ruleId` all keep working without anyone having to\n * reserve a vocabulary. See ADR-0016.\n */\nexport type ProjectRuleId = `project:${string}`;\n\n/** Any rule that can produce a finding: built in, or written by a repository. */\nexport type AnyRuleId = RuleId | ProjectRuleId;\n\n/** True for an id in the project namespace, as opposed to a built-in. */\nexport function isProjectRule(rule: AnyRuleId): rule is ProjectRuleId {\n return rule.startsWith(PROJECT_RULE_PREFIX);\n}\n\nexport const PROJECT_RULE_PREFIX = 'project:';\n\nexport interface RelatedLocation {\n readonly at: SourceRef;\n readonly note: string;\n}\n\nexport interface Diagnostic {\n readonly rule: AnyRuleId;\n readonly severity: Exclude<Severity, 'off'>;\n /** One line, no trailing period. The headline of the finding. */\n readonly message: string;\n /** Where a human should go to fix it. */\n readonly at: SourceRef;\n /** Node ids involved, most relevant first. */\n readonly nodes: readonly string[];\n /**\n * What within the document this finding is about, where that is not a node.\n *\n * `null` everywhere else, where `nodes` already names the subject. It exists\n * because a broken reference names something that is not a node - that is\n * what makes it broken - and a baseline still has to be able to tell one\n * broken reference from another. A misread front-matter key is the same\n * shape: a spelling, not a node. See ADR-0012.\n */\n readonly target: string | null;\n /** Supporting locations: the other end of an edge, a cycle members. */\n readonly related: readonly RelatedLocation[];\n /** Concrete next action. */\n readonly hint: string;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Analysis output */\n/* -------------------------------------------------------------------------- */\n\n/** A problem with the input itself, as opposed to a finding about the graph. */\nexport interface ParseProblem {\n readonly message: string;\n readonly at: SourceRef;\n /**\n * Front matter held something the graph is built from - a status, an id, an\n * alias or a relation, or the whole block - and it was not read. Problems\n * are listed under `--verbose`, and these are counted without it: a status\n * left out reads as unknown, which can turn a failing check into a passing\n * one.\n */\n readonly unread?: boolean | undefined;\n}\n\nexport interface AnalysisSummary {\n readonly documents: number;\n readonly items: number;\n readonly edges: number;\n readonly openObligations: number;\n readonly errors: number;\n readonly warnings: number;\n readonly infos: number;\n /** Milliseconds, wall clock. */\n readonly durationMs: number;\n}\n"]}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * A reader and editor for the front matter the spec-* tools use: a flat bag
3
+ * of YAML scalars and lists, and optionally one level of nested mapping.
4
+ *
5
+ * Supported: `key: value` lines; plain, single-quoted and double-quoted
6
+ * scalars; inline `[a, b]` sequences; block `- item` sequences; `#` comments.
7
+ * Plain scalars follow the YAML 1.2 core schema, so `yes` is a word and `035`
8
+ * keeps its leading zero for whoever reads it as text. With `nested`, a key
9
+ * whose value is an indented block of keys is read as `parent.child` entries.
10
+ *
11
+ * Anything richer - deeper nesting, block scalars, anchors, tags, a value
12
+ * continued onto the next line - is recognised and reported as unsupported
13
+ * rather than guessed at. A YAML library would parse more, but it would not
14
+ * give back the line and the offset of every value, and a report has to point
15
+ * at the value it is about, and an edit has to leave every other line of the
16
+ * file as it was.
17
+ */
18
+ import type { FrontMatterKind } from './types.js';
19
+ export interface YamlScalar {
20
+ readonly text: string;
21
+ readonly quoted: boolean;
22
+ }
23
+ export type YamlValue = {
24
+ readonly kind: 'scalar';
25
+ readonly scalar: YamlScalar;
26
+ } | {
27
+ readonly kind: 'list';
28
+ readonly items: readonly YamlScalar[];
29
+ } | {
30
+ readonly kind: 'unsupported';
31
+ readonly reason: string;
32
+ };
33
+ export interface FrontMatterEntry {
34
+ /** The key as written; a nested key is its parent's and its own, joined by a dot. */
35
+ readonly key: string;
36
+ /** The key compared: {@link keyName} of `key`, so `depends-on` is `dependsOn`. */
37
+ readonly name: string;
38
+ /** The parent key as written, for a nested key; `null` at the top level. */
39
+ readonly parent: string | null;
40
+ /** 0-based line of the key. */
41
+ readonly line: number;
42
+ /** 0-based line after the entry's last line. */
43
+ readonly end: number;
44
+ /** Offset of the key in the text read. */
45
+ readonly keyStart: number;
46
+ /**
47
+ * Offsets of the value as written: a quoted scalar with its quotes, an
48
+ * inline list with its brackets, a block list from its first item's text to
49
+ * its last item's. An empty value is the empty range just past the colon.
50
+ */
51
+ readonly valueStart: number;
52
+ readonly valueEnd: number;
53
+ readonly value: YamlValue;
54
+ }
55
+ export interface FrontMatterProblem {
56
+ /** 0-based line. */
57
+ readonly line: number;
58
+ readonly message: string;
59
+ }
60
+ export interface FrontMatter {
61
+ readonly kind: FrontMatterKind;
62
+ /** 0-based line of the closing delimiter, or -1 when the block is never closed. */
63
+ readonly close: number;
64
+ readonly entries: readonly FrontMatterEntry[];
65
+ readonly problems: readonly FrontMatterProblem[];
66
+ }
67
+ export interface ReadOptions {
68
+ /**
69
+ * Read one level of nested mapping as `parent.child` entries, instead of
70
+ * reporting the parent's value as unsupported.
71
+ */
72
+ readonly nested?: boolean;
73
+ }
74
+ /** The kind of front matter a document's first line opens, or `null` when it opens none. */
75
+ export declare function frontMatterKind(firstLine: string): FrontMatterKind | null;
76
+ /** Whether a line closes front matter of a kind: `---` or `...` for YAML, `+++` for TOML. */
77
+ export declare function frontMatterCloses(line: string, kind: FrontMatterKind): boolean;
78
+ export declare function keyName(key: string): string;
79
+ /**
80
+ * Reads the front matter at the top of a text, or `null` when there is none.
81
+ *
82
+ * A leading byte-order mark is not part of the text read: offsets count from
83
+ * the character after it, as a scan's do.
84
+ */
85
+ export declare function readFrontMatter(source: string, options?: ReadOptions): FrontMatter | null;
86
+ /** Parses a value written on the key's own line. `text` is trimmed and non-empty. */
87
+ export declare function parseInline(text: string): YamlValue;
88
+ /** Null in the YAML 1.2 core schema: empty, `~` or `null` in any of its three spellings. */
89
+ export declare function isNull(scalar: YamlScalar): boolean;
90
+ /** Renders a string as a scalar that reads back as the same string. */
91
+ export declare function renderScalar(value: string): string;
92
+ export declare function findEntry(frontMatter: FrontMatter | null, key: string): FrontMatterEntry | undefined;
93
+ /**
94
+ * Sets one key, leaving every other line as it was.
95
+ *
96
+ * `lines` are the lines of the text the front matter was read from, as
97
+ * `splitLines` gives them. An existing entry keeps the spelling and the
98
+ * indentation of its key; a new one goes last, at the top level. A text with
99
+ * no front matter gains a block.
100
+ */
101
+ export declare function setEntry(lines: readonly string[], frontMatter: FrontMatter | null, key: string, rendered: string): string[];
102
+ /** Removes one key and its value lines; a key that is absent changes nothing. */
103
+ export declare function removeEntry(lines: readonly string[], frontMatter: FrontMatter | null, key: string): string[];