@descent-vtt/spec-graph 0.5.0 → 0.7.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.
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Output formatting.\n *\n * Two audiences, one set of facts. In a terminal the report leads with the file\n * and line so an editor can jump there, indents the supporting evidence, and\n * ends with a concrete next action - because a finding a reader cannot act on\n * is a finding they will learn to scroll past. In CI it emits JSON with every\n * position intact, so a bot can annotate a diff.\n *\n * Colour is opt-out and auto-detected, and the glyphs degrade to ASCII when the\n * terminal cannot render them.\n */\n\nimport { fingerprintOf, type StaleEntry } from './baseline.js';\nimport type { SpecGraph } from './graph.js';\nimport type { ProjectRule } from './project-rules.js';\nimport { formatRef } from './source.js';\nimport { DEFAULT_SEVERITIES, RULE_DESCRIPTIONS, RULE_IDS } from './rules.js';\nimport type { AnalysisResult } from './runner.js';\nimport type {\n AnyRuleId,\n Diagnostic,\n Edge,\n RuleId,\n Severity,\n SourceRef,\n SpecNode,\n SuppressedRef,\n} from './types.js';\n\nexport interface ReporterOptions {\n readonly color?: boolean | undefined;\n readonly ascii?: boolean | undefined;\n readonly verbose?: boolean | undefined;\n /** Stop after this many findings. `0` means no limit. */\n readonly max?: number | undefined;\n /**\n * Rules whose severity `--strict` raised.\n *\n * A finding that only became an error because of a flag has to say so, or the\n * reader cannot tell what would happen without it.\n */\n readonly escalated?: ReadonlySet<AnyRuleId> | undefined;\n /**\n * What a baseline accounted for on this run.\n *\n * Reported as counts rather than as a list: the point of accepted debt is\n * that nobody has to read it every time. `stale` is the ratchet - debt the\n * run did not spend and which can be struck from the file - and `ratchet`\n * says whether this run was asked to fail over it.\n *\n * `entries` carries the stale ones themselves, for the structured formats. A\n * number is enough to know the file has slack and never enough to strike it,\n * and a bot that wants to open the pull request needs the rows.\n */\n readonly baseline?:\n | {\n readonly source: string;\n readonly suppressed: number;\n readonly stale: number;\n readonly ratchet?: boolean | undefined;\n readonly entries?: readonly StaleEntry[] | undefined;\n }\n | undefined;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Environment detection */\n/* -------------------------------------------------------------------------- */\n\nexport interface ColorEnvironment {\n readonly isTTY?: boolean | undefined;\n readonly env?: Readonly<Record<string, string | undefined>> | undefined;\n /**\n * Host platform, defaulting to the real one.\n *\n * Injected for the same reason `env` is: without it half of\n * {@link shouldUseAscii} is unreachable from a test, and a rule about\n * Windows consoles that only Windows can exercise is a rule that breaks on\n * Windows and nowhere else.\n */\n readonly platform?: NodeJS.Platform | undefined;\n}\n\n/** Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to TTY. */\nexport function shouldUseColor(environment: ColorEnvironment = {}): boolean {\n const env = environment.env ?? process.env;\n if (env['NO_COLOR'] !== undefined && env['NO_COLOR'] !== '') return false;\n // `FORCE_COLOR=0` is the conventional way to turn colour off, so it has to\n // win over an attached TTY rather than merely failing to force it on.\n if (env['FORCE_COLOR'] === '0') return false;\n if (env['FORCE_COLOR'] !== undefined && env['FORCE_COLOR'] !== '') return true;\n if (env['TERM'] === 'dumb') return false;\n if (env['CI'] !== undefined && env['CI'] !== '') return false;\n return environment.isTTY === true;\n}\n\n/** True when the terminal is unlikely to render box-drawing and arrows. */\nexport function shouldUseAscii(environment: ColorEnvironment = {}): boolean {\n const env = environment.env ?? process.env;\n if (env['SPEC_GRAPH_ASCII'] !== undefined && env['SPEC_GRAPH_ASCII'] !== '') return true;\n if ((environment.platform ?? process.platform) !== 'win32') return false;\n // Windows Terminal and modern shells set these; the legacy console does not.\n return env['WT_SESSION'] === undefined && env['TERM_PROGRAM'] === undefined;\n}\n\nconst EMPTY_RULES: ReadonlySet<RuleId> = new Set<RuleId>();\n\ntype Paint = (text: string) => string;\n\nexport interface Painter {\n readonly error: Paint;\n readonly warn: Paint;\n readonly info: Paint;\n readonly dim: Paint;\n readonly bold: Paint;\n readonly hint: Paint;\n readonly location: Paint;\n}\n\nexport function createPainter(color: boolean): Painter {\n const wrap = (open: string): Paint => (text) => (color ? `\\u001b[${open}m${text}\\u001b[0m` : text);\n return {\n error: wrap('31'),\n warn: wrap('33'),\n info: wrap('36'),\n dim: wrap('2'),\n bold: wrap('1'),\n hint: wrap('32'),\n location: wrap('4'),\n };\n}\n\ninterface Glyphs {\n readonly error: string;\n readonly warn: string;\n readonly info: string;\n readonly related: string;\n readonly hint: string;\n readonly separator: string;\n}\n\nfunction glyphs(ascii: boolean): Glyphs {\n return ascii\n ? { error: 'x', warn: '!', info: 'i', related: '|', hint: '>', separator: '-' }\n : { error: '\\u2716', warn: '\\u26a0', info: '\\u2139', related: '\\u21b3', hint: '\\u2192', separator: '\\u00b7' };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Human report */\n/* -------------------------------------------------------------------------- */\n\n/** Renders the full terminal report. */\nexport function formatReport(result: AnalysisResult, options: ReporterOptions = {}): string {\n const paint = createPainter(options.color ?? false);\n const marks = glyphs(options.ascii ?? false);\n const lines: string[] = [];\n const { summary } = result;\n\n lines.push(\n `${paint.bold('spec-graph')} ${paint.dim(\n [\n `${summary.documents} ${plural(summary.documents, 'document')}`,\n `${summary.items} ${plural(summary.items, 'item')}`,\n `${summary.edges} ${plural(summary.edges, 'relation')}`,\n `${summary.openObligations} open`,\n ].join(` ${marks.separator} `),\n )}`,\n );\n lines.push('');\n\n const limit = options.max && options.max > 0 ? options.max : result.diagnostics.length;\n const shown = result.diagnostics.slice(0, limit);\n\n const escalated = options.escalated ?? EMPTY_RULES;\n for (const diagnostic of shown) {\n lines.push(...formatDiagnostic(diagnostic, paint, marks, escalated));\n lines.push('');\n }\n\n if (result.diagnostics.length > shown.length) {\n lines.push(paint.dim(` ... and ${result.diagnostics.length - shown.length} more`));\n lines.push('');\n }\n\n if (options.verbose && result.problems.length > 0) {\n for (const problem of result.problems) {\n lines.push(`${paint.warn(marks.warn)} ${paint.location(formatRef(problem.at))} ${problem.message}`);\n }\n lines.push('');\n }\n\n // What the repository told spec-graph to stop looking at. Only under\n // --verbose, and never as a finding: these are not defects, they are the one\n // place a configuration can make the check quieter, and a single over-broad\n // glob looks exactly like a clean repository from the outside. See ADR-0008.\n if (options.verbose && result.corpus.suppressed.length > 0) {\n for (const [target, entry] of groupSuppressed(result.corpus.suppressed)) {\n const where = entry.by === 'family' ? 'ignored family' : 'ignored reference';\n const times = entry.count === 1 ? '' : ` (${entry.count} times)`;\n lines.push(`${paint.dim(marks.info)} ${paint.location(formatRef(entry.at))} ${paint.dim(`${where}: ${target}${times}`)}`);\n }\n lines.push('');\n }\n\n const tally: string[] = [];\n if (summary.errors > 0) tally.push(paint.error(`${summary.errors} ${plural(summary.errors, 'error')}`));\n if (summary.warnings > 0) tally.push(paint.warn(`${summary.warnings} ${plural(summary.warnings, 'warning')}`));\n if (summary.infos > 0) tally.push(paint.info(`${summary.infos} ${plural(summary.infos, 'note')}`));\n tally.push(paint.dim(`${summary.durationMs}ms`));\n const raised = result.diagnostics.filter((diagnostic) => escalated.has(diagnostic.rule)).length;\n if (raised > 0) {\n tally.push(paint.warn(`${raised} raised by --strict`));\n }\n const baseline = options.baseline;\n if (baseline !== undefined && baseline.suppressed > 0) {\n tally.push(paint.dim(`${baseline.suppressed} accepted by ${baseline.source}`));\n }\n lines.push(tally.join(` ${marks.separator} `));\n\n // Under `--ratchet` a paid entry is a failure rather than a note, so it is\n // painted and worded as one.\n const ratcheted = ratchetFailed(baseline);\n if (baseline !== undefined && baseline.stale > 0) {\n // A \"gone\" entry is not the ratchet working, and saying so matters more\n // than the count does: the usual way to produce one is to narrow an include\n // pattern, which loses sight of a defect rather than fixing it.\n const gone = (baseline.entries ?? []).filter((entry) => entry.reason === 'gone').length;\n const because =\n gone === 0\n ? `tighten it: spec-graph check --record-baseline ${baseline.source}`\n : `${gone} of them ${gone === 1 ? 'names a document' : 'name documents'} this run did not see - check the include patterns before re-recording`;\n const text = `${baseline.stale} baseline ${plural(baseline.stale, 'entry', 'entries')} no longer ${\n baseline.stale === 1 ? 'occurs' : 'occur'\n } - ${because}`;\n lines.push(ratcheted ? `${paint.error(marks.error)} ${text}` : paint.dim(text));\n }\n\n lines.push(\n ratcheted\n ? `${paint.error(marks.error)} ${\n result.ok ? 'the baseline is looser than the repository' : 'the specification graph is inconsistent'\n }`\n : result.ok\n ? `${paint.hint(marks.hint === '>' ? 'ok' : '\\u2714')} ${\n summary.errors + summary.warnings === 0\n ? 'the specification graph is consistent'\n : 'no errors - the specification graph holds'\n }`\n : `${paint.error(marks.error)} the specification graph is inconsistent`,\n );\n\n return lines.join('\\n');\n}\n\nfunction formatDiagnostic(\n diagnostic: Diagnostic,\n paint: Painter,\n marks: Glyphs,\n escalated: ReadonlySet<AnyRuleId>,\n): string[] {\n const mark = severityMark(diagnostic.severity, paint, marks);\n const label = escalated.has(diagnostic.rule)\n ? `${diagnostic.rule} ${paint.warn('(strict: warn -> error)')}`\n : diagnostic.rule;\n const lines: string[] = [\n `${mark} ${paint.location(formatRef(diagnostic.at))} ${paint.dim(label)}`,\n ` ${diagnostic.message}`,\n ];\n\n const width = Math.max(0, ...diagnostic.related.map((entry) => formatRef(entry.at).length));\n for (const entry of diagnostic.related) {\n const reference = formatRef(entry.at);\n lines.push(` ${paint.dim(marks.related)} ${paint.dim(reference.padEnd(width))} ${paint.dim(entry.note)}`);\n }\n\n lines.push(` ${paint.hint(marks.hint)} ${paint.hint(diagnostic.hint)}`);\n return lines;\n}\n\nfunction severityMark(severity: Exclude<Severity, 'off'>, paint: Painter, marks: Glyphs): string {\n switch (severity) {\n case 'error':\n return paint.error(marks.error);\n case 'warn':\n return paint.warn(marks.warn);\n case 'info':\n return paint.info(marks.info);\n }\n}\n\nfunction plural(count: number, word: string, plural?: string): string {\n if (count === 1) return word;\n return plural ?? `${word}s`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Markdown */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The same report as GitHub-flavoured Markdown.\n *\n * SARIF puts a finding on the line that caused it, which is where somebody\n * fixing one wants it. It says nothing to the person deciding whether to merge,\n * because a code-scanning alert is a list of lines and not a verdict. This is\n * the verdict: one table, the counts above it, and the baseline's slack\n * underneath, sized to be read without scrolling.\n *\n * Written for `$GITHUB_STEP_SUMMARY` and for a pull-request comment, but it is\n * named for what it is rather than for where it goes - the same text is what a\n * review tool, a chat message or a generated page wants.\n *\n * It carries no duration, which the JSON report does, so two runs over one\n * corpus produce identical bytes. That is what lets a test compare a run from\n * a subdirectory against a run from the root and assert they are the same\n * report rather than the same shape. See ADR-0015 and ADR-0018.\n */\nexport function formatMarkdown(result: AnalysisResult, options: ReporterOptions = {}): string {\n const { summary } = result;\n const escalated = options.escalated ?? EMPTY_RULES;\n const ratcheted = ratchetFailed(options.baseline);\n const lines: string[] = ['### spec-graph', ''];\n\n const verdict =\n ratcheted && result.ok\n ? 'The baseline is looser than the repository.'\n : result.ok\n ? summary.errors + summary.warnings === 0\n ? 'The specification graph is consistent.'\n : 'No errors - the specification graph holds.'\n : 'The specification graph is inconsistent.';\n lines.push(verdict, '');\n\n lines.push('| | |', '| --- | ---: |');\n lines.push(`| Documents | ${summary.documents} |`);\n lines.push(`| Items | ${summary.items} |`);\n lines.push(`| Relations | ${summary.edges} |`);\n lines.push(`| Open obligations | ${summary.openObligations} |`);\n lines.push(`| Errors | ${summary.errors} |`);\n lines.push(`| Warnings | ${summary.warnings} |`);\n lines.push(`| Notes | ${summary.infos} |`);\n lines.push('');\n\n const limit = options.max && options.max > 0 ? options.max : result.diagnostics.length;\n const shown = result.diagnostics.slice(0, limit);\n\n if (shown.length > 0) {\n lines.push('| | Rule | Where | Finding |', '| --- | --- | --- | --- |');\n for (const diagnostic of shown) {\n const rule = escalated.has(diagnostic.rule) ? `${diagnostic.rule} (strict)` : diagnostic.rule;\n // The hint in the same cell, under the message. A finding without its\n // next action is the half a reader cannot act on, and a fifth column\n // would push the message off the side of the page.\n const what = `${cell(diagnostic.message)}<br>${cell(diagnostic.hint)}`;\n lines.push(`| ${diagnostic.severity} | \\`${cell(rule)}\\` | \\`${cell(formatRef(diagnostic.at))}\\` | ${what} |`);\n }\n if (result.diagnostics.length > shown.length) {\n lines.push(`| | | | ... and ${result.diagnostics.length - shown.length} more |`);\n }\n lines.push('');\n }\n\n const baseline = options.baseline;\n if (baseline !== undefined) {\n const accepted = `${baseline.suppressed} ${plural(baseline.suppressed, 'finding')} accepted by \\`${cell(baseline.source)}\\``;\n if (baseline.stale === 0) {\n lines.push(accepted, '');\n } else {\n const gone = (baseline.entries ?? []).filter((entry) => entry.reason === 'gone').length;\n lines.push(\n `${accepted}, and ${baseline.stale} ${plural(baseline.stale, 'entry', 'entries')} no longer ${\n baseline.stale === 1 ? 'occurs' : 'occur'\n }${\n gone === 0\n ? ''\n : ` - ${gone} of them ${gone === 1 ? 'names a document' : 'name documents'} this run did not see`\n }.`,\n '',\n );\n // Listed rather than counted, because the point of a summary on a pull\n // request is that somebody can act on it without opening a terminal.\n lines.push('| Entry | Rule | Document | Why |', '| --- | --- | --- | --- |');\n for (const entry of baseline.entries ?? []) {\n const why = entry.reason === 'gone' ? 'not in this corpus - check the include patterns' : 'fixed';\n lines.push(`| ${entry.reason} | \\`${cell(entry.rule)}\\` | \\`${cell(entry.document)}\\` | ${why} |`);\n }\n lines.push('');\n }\n }\n\n if (options.verbose && result.problems.length > 0) {\n lines.push('<details><summary>Problems with the input</summary>', '');\n for (const problem of result.problems) {\n lines.push(`- \\`${cell(formatRef(problem.at))}\\` ${cell(problem.message)}`);\n }\n lines.push('', '</details>', '');\n }\n\n if (options.verbose && result.corpus.suppressed.length > 0) {\n lines.push('<details><summary>References this configuration silenced</summary>', '');\n for (const [target, entry] of groupSuppressed(result.corpus.suppressed)) {\n const where = entry.by === 'family' ? 'ignored family' : 'ignored reference';\n const times = entry.count === 1 ? '' : ` (${entry.count} times)`;\n lines.push(`- \\`${cell(target)}\\` - ${where}${times}, first at \\`${cell(formatRef(entry.at))}\\``);\n }\n lines.push('', '</details>', '');\n }\n\n return `${lines.join('\\n').replace(/\\n+$/, '')}\\n`;\n}\n\n/**\n * Makes one value safe to put in a table cell.\n *\n * A pipe would end the cell and a newline would end the row, and a diagnostic\n * message is written by whoever wrote the rule - including a project rule,\n * whose message is a template a repository controls.\n */\nfunction cell(value: string): string {\n return value.replace(/[|]/g, '&#124;').replace(/\\s+/g, ' ').trim();\n}\n\n/* -------------------------------------------------------------------------- */\n/* JSON */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The machine-readable report.\n *\n * Deliberately flat and versioned: this is the contract a CI annotator or a\n * dashboard builds against, and it must be safe to add fields to it later.\n */\n/**\n * One row per silenced target, with the first place it was written.\n *\n * Grouped because a concept tag used forty times is one decision, and forty\n * lines of it would bury the one entry somebody needs to see. Insertion order\n * is document order, which is already deterministic.\n */\nfunction groupSuppressed(\n suppressed: readonly SuppressedRef[],\n): Map<string, { at: SourceRef; by: SuppressedRef['by']; count: number }> {\n const out = new Map<string, { at: SourceRef; by: SuppressedRef['by']; count: number }>();\n for (const entry of suppressed) {\n const seen = out.get(entry.target);\n if (seen === undefined) out.set(entry.target, { at: entry.at, by: entry.by, count: 1 });\n else seen.count += 1;\n }\n return out;\n}\n\n/**\n * True when a baseline was asked to ratchet and has slack left in it.\n *\n * Both reporters ask, because both have to agree with the exit code: a report\n * that prints \"ok\" above a failing build is worse than no report.\n */\nfunction ratchetFailed(baseline: ReporterOptions['baseline']): boolean {\n return baseline !== undefined && baseline.ratchet === true && baseline.stale > 0;\n}\n\n/* -------------------------------------------------------------------------- */\n/* SARIF */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The static-analysis interchange format, for the tools that already read it.\n *\n * The reason to emit it is not the format, it is what consumes the format:\n * GitHub code scanning turns a SARIF upload into annotations on the diff, and\n * an editor turns it into the problems pane, neither of which needs a line of\n * spec-graph-specific integration.\n *\n * One field earns the whole exercise. `partialFingerprints` is how a consumer\n * tracks a finding across commits without keying on a line number, and\n * spec-graph already has exactly that identifier for exactly that reason - the\n * `rule/document/subject` triple a baseline is keyed on (ADR-0012). The two\n * problems turned out to be the same problem, so the answer is the same answer.\n *\n * Deterministic and timestamp-free, like every other output here. Nothing about\n * a run that has the same findings should produce a different file.\n */\nexport function formatSarif(\n result: AnalysisResult,\n graph: SpecGraph,\n options: {\n version?: string | undefined;\n escalated?: ReadonlySet<AnyRuleId> | undefined;\n projectRules?: readonly ProjectRule[] | undefined;\n } = {},\n): string {\n const escalated = options.escalated ?? EMPTY_RULES;\n // A project rule describes itself by the selector it is, because that is the\n // only honest answer: its message is a template, and a template with `{0}` in\n // it is not a description of anything. See ADR-0016.\n const known: [AnyRuleId, string, Severity][] = [\n ...RULE_IDS.map((id): [AnyRuleId, string, Severity] => [id, RULE_DESCRIPTIONS[id], DEFAULT_SEVERITIES[id]]),\n ...(options.projectRules ?? []).map((rule): [AnyRuleId, string, Severity] => [\n rule.id,\n rule.sources.join(' | '),\n rule.severity,\n ]),\n ];\n const fired = known.filter(([id]) => result.diagnostics.some((diagnostic) => diagnostic.rule === id));\n return `${JSON.stringify(\n {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: 'spec-graph',\n informationUri: 'https://github.com/DescentVTT/spec-graph',\n ...(options.version === undefined ? {} : { version: options.version, semanticVersion: options.version }),\n // Only the rules that fired. A driver listing all of them\n // describes the tool; this file describes the run.\n rules: fired.map(([id, description, level]) => ({\n id,\n shortDescription: { text: description },\n defaultConfiguration: { level: sarifLevel(level) },\n })),\n },\n },\n results: result.diagnostics.map((diagnostic) => {\n const print = fingerprintOf(graph, diagnostic);\n return {\n ruleId: diagnostic.rule,\n level: sarifLevel(diagnostic.severity),\n message: { text: `${diagnostic.message}. ${diagnostic.hint}` },\n locations: [sarifLocation(diagnostic.at)],\n ...(diagnostic.related.length === 0\n ? {}\n : {\n relatedLocations: diagnostic.related.map((entry) => ({\n ...sarifLocation(entry.at),\n message: { text: entry.note },\n })),\n }),\n partialFingerprints: {\n specGraphIdentity: `${diagnostic.rule}/${print.document}/${print.subject}`,\n },\n properties: {\n nodes: diagnostic.nodes,\n target: diagnostic.target,\n // A finding that is only an error because of a flag says so\n // here too, so a reviewer reading an annotation is not misled.\n escalated: escalated.has(diagnostic.rule),\n },\n };\n }),\n },\n ],\n },\n null,\n 2,\n )}\\n`;\n}\n\nfunction sarifLevel(severity: Severity): string {\n switch (severity) {\n case 'error':\n return 'error';\n case 'warn':\n return 'warning';\n case 'info':\n return 'note';\n default:\n return 'none';\n }\n}\n\nfunction sarifLocation(at: SourceRef): {\n physicalLocation: {\n artifactLocation: { uri: string };\n region: { startLine: number; startColumn: number; endLine: number; endColumn: number };\n };\n} {\n return {\n physicalLocation: {\n // Already repository-relative and POSIX, which is what SARIF asks for.\n artifactLocation: { uri: at.file },\n region: {\n startLine: at.span.start.line,\n startColumn: at.span.start.column,\n endLine: at.span.end.line,\n endColumn: at.span.end.column,\n },\n },\n };\n}\n\nexport function formatJson(\n result: AnalysisResult,\n options: { escalated?: ReadonlySet<AnyRuleId>; baseline?: ReporterOptions['baseline'] } = {},\n): string {\n const escalated = options.escalated ?? EMPTY_RULES;\n return `${JSON.stringify(\n {\n version: 1,\n ok: result.ok && !ratchetFailed(options.baseline),\n strict: escalated.size > 0,\n ...(options.baseline === undefined ? {} : { baseline: options.baseline }),\n summary: result.summary,\n files: result.files,\n // The audit trail for what configuration silenced. Always present, unlike\n // the human report's --verbose gate: a machine reader that has to ask for\n // it twice will not ask. See ADR-0008.\n suppressed: result.corpus.suppressed.map((entry) => ({\n target: entry.target,\n from: entry.from,\n by: entry.by,\n file: entry.at.file,\n line: entry.at.span.start.line,\n })),\n diagnostics: result.diagnostics.map((diagnostic) => ({\n rule: diagnostic.rule,\n severity: diagnostic.severity,\n // True when this finding is only an error because of --strict.\n escalated: escalated.has(diagnostic.rule),\n message: diagnostic.message,\n hint: diagnostic.hint,\n nodes: diagnostic.nodes,\n target: diagnostic.target,\n file: diagnostic.at.file,\n line: diagnostic.at.span.start.line,\n column: diagnostic.at.span.start.column,\n endLine: diagnostic.at.span.end.line,\n endColumn: diagnostic.at.span.end.column,\n related: diagnostic.related.map((entry) => ({\n file: entry.at.file,\n line: entry.at.span.start.line,\n column: entry.at.span.start.column,\n note: entry.note,\n })),\n })),\n problems: result.problems.map((problem) => ({\n message: problem.message,\n file: problem.at.file,\n line: problem.at.span.start.line,\n })),\n },\n null,\n 2,\n )}\\n`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Graph export */\n/* -------------------------------------------------------------------------- */\n\nexport type GraphFormat = 'dot' | 'mermaid' | 'json';\n\nexport interface GraphExportOptions {\n /** Leave out `contains` edges and item nodes. */\n readonly documentsOnly?: boolean | undefined;\n}\n\n/** Serialises the graph for Graphviz, Mermaid, or a downstream tool. */\nexport function formatGraph(graph: SpecGraph, format: GraphFormat, options: GraphExportOptions = {}): string {\n const skipItems = options.documentsOnly ?? false;\n const nodes = [...graph.nodes.values()].filter((node) => !skipItems || node.kind === 'document');\n const visible = new Set(nodes.map((node) => node.id));\n\n // Hiding items must not hide what they say. An obligation delegated from an\n // item to a document is lifted onto the item's owner, so the document-level\n // view still shows the handover rather than silently losing it.\n const lifted = skipItems\n ? dedupeEdges(\n graph.edges\n // Containment of an *item* is what hiding items makes redundant.\n // Containment of a specification by the register that holds it is\n // structure between documents, and is what this view exists to show.\n .filter((edge) => edge.kind !== 'contains' || visible.has(edge.to))\n .map((edge) => {\n const from = graph.owningDocument(edge.from)?.id ?? edge.from;\n const to = graph.owningDocument(edge.to)?.id ?? edge.to;\n return from === edge.from && to === edge.to ? edge : { ...edge, from, to, reflexive: from === to };\n })\n .filter((edge) => !edge.reflexive),\n )\n : graph.edges;\n\n const edges = lifted.filter((edge) => visible.has(edge.from) && visible.has(edge.to));\n\n switch (format) {\n case 'dot':\n return toDot(nodes, edges);\n case 'mermaid':\n return toMermaid(nodes, edges);\n case 'json':\n return `${JSON.stringify(\n {\n version: 1,\n nodes: nodes.map(serialiseNode),\n edges: edges.map((edge) => ({\n kind: edge.kind,\n from: edge.from,\n to: edge.to,\n origin: edge.origin,\n declaredIn: edge.declaredIn,\n file: edge.declaredAt.file,\n line: edge.declaredAt.span.start.line,\n })),\n },\n null,\n 2,\n )}\\n`;\n }\n}\n\n/** Collapses duplicate relations produced by lifting item edges onto documents. */\nfunction dedupeEdges(edges: readonly Edge[]): Edge[] {\n const seen = new Set<string>();\n const out: Edge[] = [];\n for (const edge of edges) {\n const key = `${edge.kind} ${edge.from} ${edge.to}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(edge);\n }\n return out;\n}\n\nfunction serialiseNode(node: SpecNode): Record<string, unknown> {\n const base = {\n id: node.id,\n kind: node.kind,\n title: node.title,\n file: node.at.file,\n line: node.at.span.start.line,\n };\n return node.kind === 'document'\n ? { ...base, path: node.path, phase: node.phase, status: node.rawStatus, aliases: node.aliases }\n : {\n ...base,\n document: node.document,\n section: node.section,\n disposition: node.disposition,\n openness: node.openness,\n };\n}\n\n/** Phase colours, chosen to stay legible in both light and dark renderings. */\nconst PHASE_FILL: Readonly<Record<string, string>> = {\n draft: '#e8f0fe',\n active: '#e6f4ea',\n frozen: '#e8eaed',\n retired: '#fce8e6',\n record: '#f3e8fd',\n unknown: '#ffffff',\n};\n\nfunction toDot(nodes: readonly SpecNode[], edges: readonly Edge[]): string {\n const lines = ['digraph spec {', ' rankdir=LR;', ' node [shape=box, style=\"rounded,filled\", fontname=\"sans\"];'];\n for (const node of nodes) {\n const fill = node.kind === 'document' ? (PHASE_FILL[node.phase] ?? '#ffffff') : '#fffbe6';\n const label = node.kind === 'document' ? `${node.id}\\\\n${escapeDot(node.title)}` : escapeDot(node.text);\n const shape = node.kind === 'document' ? 'box' : 'note';\n lines.push(` \"${escapeDot(node.id)}\" [label=\"${label}\", fillcolor=\"${fill}\", shape=${shape}];`);\n }\n for (const edge of edges) {\n const style = edge.kind === 'contains' ? ', style=dotted' : '';\n lines.push(` \"${escapeDot(edge.from)}\" -> \"${escapeDot(edge.to)}\" [label=\"${edge.kind}\"${style}];`);\n }\n lines.push('}');\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction toMermaid(nodes: readonly SpecNode[], edges: readonly Edge[]): string {\n const lines = ['graph LR'];\n const alias = new Map<string, string>();\n nodes.forEach((node, position) => alias.set(node.id, `n${position}`));\n\n for (const node of nodes) {\n const key = alias.get(node.id) as string;\n const label = escapeMermaid(node.kind === 'document' ? node.id : node.text);\n lines.push(node.kind === 'document' ? ` ${key}[\"${label}\"]` : ` ${key}([\"${label}\"])`);\n if (node.kind === 'document' && node.phase !== 'unknown') lines.push(` class ${key} ${node.phase};`);\n }\n for (const edge of edges) {\n const from = alias.get(edge.from);\n const to = alias.get(edge.to);\n if (!from || !to) continue;\n lines.push(` ${from} -->|${edge.kind}| ${to}`);\n }\n for (const [phase, fill] of Object.entries(PHASE_FILL)) {\n if (phase === 'unknown') continue;\n lines.push(` classDef ${phase} fill:${fill},stroke:#5f6368;`);\n }\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction escapeDot(value: string): string {\n return value.replace(/[\"\\\\]/g, '\\\\$&').replace(/\\n/g, '\\\\n');\n}\n\nfunction escapeMermaid(value: string): string {\n return value.replace(/[\"#]/g, ' ').replace(/\\s+/g, ' ').trim();\n}\n"]}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Output formatting.\n *\n * Two audiences, one set of facts. In a terminal the report leads with the file\n * and line so an editor can jump there, indents the supporting evidence, and\n * ends with a concrete next action - because a finding a reader cannot act on\n * is a finding they will learn to scroll past. In CI it emits JSON with every\n * position intact, so a bot can annotate a diff.\n *\n * Colour is opt-out and auto-detected, and the glyphs degrade to ASCII when the\n * terminal cannot render them.\n */\n\nimport { fingerprintOf, type StaleEntry } from './baseline.js';\nimport type { SpecGraph } from './graph.js';\nimport type { ProjectRule } from './project-rules.js';\nimport { formatRef } from './source.js';\nimport { DEFAULT_SEVERITIES, RULE_DESCRIPTIONS, RULE_IDS } from './rules.js';\nimport type { AnalysisResult } from './runner.js';\nimport type {\n AnyRuleId,\n Diagnostic,\n Edge,\n RuleId,\n Severity,\n SourceRef,\n SpecNode,\n SuppressedRef,\n} from './types.js';\n\nexport interface ReporterOptions {\n readonly color?: boolean | undefined;\n readonly ascii?: boolean | undefined;\n readonly verbose?: boolean | undefined;\n /** Stop after this many findings. `0` means no limit. */\n readonly max?: number | undefined;\n /**\n * Rules whose severity `--strict` raised.\n *\n * A finding that only became an error because of a flag has to say so, or the\n * reader cannot tell what would happen without it.\n */\n readonly escalated?: ReadonlySet<AnyRuleId> | undefined;\n /**\n * What a baseline accounted for on this run.\n *\n * Reported as counts rather than as a list: the point of accepted debt is\n * that nobody has to read it every time. `stale` is the ratchet - debt the\n * run did not spend and which can be struck from the file - and `ratchet`\n * says whether this run was asked to fail over it.\n *\n * `entries` carries the stale ones themselves, for the structured formats. A\n * number is enough to know the file has slack and never enough to strike it,\n * and a bot that wants to open the pull request needs the rows.\n */\n readonly baseline?:\n | {\n readonly source: string;\n readonly suppressed: number;\n readonly stale: number;\n readonly ratchet?: boolean | undefined;\n readonly entries?: readonly StaleEntry[] | undefined;\n }\n | undefined;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Environment detection */\n/* -------------------------------------------------------------------------- */\n\nexport interface ColorEnvironment {\n readonly isTTY?: boolean | undefined;\n readonly env?: Readonly<Record<string, string | undefined>> | undefined;\n /**\n * Host platform, defaulting to the real one.\n *\n * Injected for the same reason `env` is: without it half of\n * {@link shouldUseAscii} is unreachable from a test, and a rule about\n * Windows consoles that only Windows can exercise is a rule that breaks on\n * Windows and nowhere else.\n */\n readonly platform?: NodeJS.Platform | undefined;\n}\n\n/** Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to TTY. */\nexport function shouldUseColor(environment: ColorEnvironment = {}): boolean {\n const env = environment.env ?? process.env;\n if (env['NO_COLOR'] !== undefined && env['NO_COLOR'] !== '') return false;\n // `FORCE_COLOR=0` is the conventional way to turn colour off, so it has to\n // win over an attached TTY rather than merely failing to force it on.\n if (env['FORCE_COLOR'] === '0') return false;\n if (env['FORCE_COLOR'] !== undefined && env['FORCE_COLOR'] !== '') return true;\n if (env['TERM'] === 'dumb') return false;\n if (env['CI'] !== undefined && env['CI'] !== '') return false;\n return environment.isTTY === true;\n}\n\n/** True when the terminal is unlikely to render box-drawing and arrows. */\nexport function shouldUseAscii(environment: ColorEnvironment = {}): boolean {\n const env = environment.env ?? process.env;\n if (env['SPEC_GRAPH_ASCII'] !== undefined && env['SPEC_GRAPH_ASCII'] !== '') return true;\n if ((environment.platform ?? process.platform) !== 'win32') return false;\n // Windows Terminal and modern shells set these; the legacy console does not.\n return env['WT_SESSION'] === undefined && env['TERM_PROGRAM'] === undefined;\n}\n\nconst EMPTY_RULES: ReadonlySet<RuleId> = new Set<RuleId>();\n\ntype Paint = (text: string) => string;\n\nexport interface Painter {\n readonly error: Paint;\n readonly warn: Paint;\n readonly info: Paint;\n readonly dim: Paint;\n readonly bold: Paint;\n readonly hint: Paint;\n readonly location: Paint;\n}\n\nexport function createPainter(color: boolean): Painter {\n const wrap = (open: string): Paint => (text) => (color ? `\\u001b[${open}m${text}\\u001b[0m` : text);\n return {\n error: wrap('31'),\n warn: wrap('33'),\n info: wrap('36'),\n dim: wrap('2'),\n bold: wrap('1'),\n hint: wrap('32'),\n location: wrap('4'),\n };\n}\n\ninterface Glyphs {\n readonly error: string;\n readonly warn: string;\n readonly info: string;\n readonly related: string;\n readonly hint: string;\n readonly separator: string;\n}\n\nfunction glyphs(ascii: boolean): Glyphs {\n return ascii\n ? { error: 'x', warn: '!', info: 'i', related: '|', hint: '>', separator: '-' }\n : { error: '\\u2716', warn: '\\u26a0', info: '\\u2139', related: '\\u21b3', hint: '\\u2192', separator: '\\u00b7' };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Human report */\n/* -------------------------------------------------------------------------- */\n\n/** Renders the full terminal report. */\nexport function formatReport(result: AnalysisResult, options: ReporterOptions = {}): string {\n const paint = createPainter(options.color ?? false);\n const marks = glyphs(options.ascii ?? false);\n const lines: string[] = [];\n const { summary } = result;\n\n lines.push(\n `${paint.bold('spec-graph')} ${paint.dim(\n [\n `${summary.documents} ${plural(summary.documents, 'document')}`,\n `${summary.items} ${plural(summary.items, 'item')}`,\n `${summary.edges} ${plural(summary.edges, 'relation')}`,\n `${summary.openObligations} open`,\n ].join(` ${marks.separator} `),\n )}`,\n );\n lines.push('');\n\n const limit = options.max && options.max > 0 ? options.max : result.diagnostics.length;\n const shown = result.diagnostics.slice(0, limit);\n\n const escalated = options.escalated ?? EMPTY_RULES;\n for (const diagnostic of shown) {\n lines.push(...formatDiagnostic(diagnostic, paint, marks, escalated));\n lines.push('');\n }\n\n if (result.diagnostics.length > shown.length) {\n lines.push(paint.dim(` ... and ${result.diagnostics.length - shown.length} more`));\n lines.push('');\n }\n\n if (options.verbose && result.problems.length > 0) {\n for (const problem of result.problems) {\n lines.push(`${paint.warn(marks.warn)} ${paint.location(formatRef(problem.at))} ${problem.message}`);\n }\n lines.push('');\n }\n\n // What the repository told spec-graph to stop looking at. Only under\n // --verbose, and never as a finding: these are not defects, they are the one\n // place a configuration can make the check quieter, and a single over-broad\n // glob looks exactly like a clean repository from the outside. See ADR-0008.\n if (options.verbose && result.corpus.suppressed.length > 0) {\n for (const [target, entry] of groupSuppressed(result.corpus.suppressed)) {\n const where = entry.by === 'family' ? 'ignored family' : 'ignored reference';\n const times = entry.count === 1 ? '' : ` (${entry.count} times)`;\n lines.push(`${paint.dim(marks.info)} ${paint.location(formatRef(entry.at))} ${paint.dim(`${where}: ${target}${times}`)}`);\n }\n lines.push('');\n }\n\n const tally: string[] = [];\n if (summary.errors > 0) tally.push(paint.error(`${summary.errors} ${plural(summary.errors, 'error')}`));\n if (summary.warnings > 0) tally.push(paint.warn(`${summary.warnings} ${plural(summary.warnings, 'warning')}`));\n if (summary.infos > 0) tally.push(paint.info(`${summary.infos} ${plural(summary.infos, 'note')}`));\n tally.push(paint.dim(`${summary.durationMs}ms`));\n const raised = result.diagnostics.filter((diagnostic) => escalated.has(diagnostic.rule)).length;\n if (raised > 0) {\n tally.push(paint.warn(`${raised} raised by --strict`));\n }\n const baseline = options.baseline;\n if (baseline !== undefined && baseline.suppressed > 0) {\n tally.push(paint.dim(`${baseline.suppressed} accepted by ${baseline.source}`));\n }\n lines.push(tally.join(` ${marks.separator} `));\n\n // Under `--ratchet` a paid entry is a failure rather than a note, so it is\n // painted and worded as one.\n const ratcheted = ratchetFailed(baseline);\n if (baseline !== undefined && baseline.stale > 0) {\n // A \"gone\" entry is not the ratchet working, and saying so matters more\n // than the count does: the usual way to produce one is to narrow an include\n // pattern, which loses sight of a defect rather than fixing it.\n const gone = (baseline.entries ?? []).filter((entry) => entry.reason === 'gone').length;\n const because =\n gone === 0\n ? `tighten it: spec-graph check --record-baseline ${baseline.source}`\n : `${gone} of them ${gone === 1 ? 'names a document' : 'name documents'} this run did not see - check the include patterns before re-recording`;\n const text = `${baseline.stale} baseline ${plural(baseline.stale, 'entry', 'entries')} no longer ${\n baseline.stale === 1 ? 'occurs' : 'occur'\n } - ${because}`;\n lines.push(ratcheted ? `${paint.error(marks.error)} ${text}` : paint.dim(text));\n }\n\n lines.push(\n ratcheted\n ? `${paint.error(marks.error)} ${\n result.ok ? 'the baseline is looser than the repository' : 'the specification graph is inconsistent'\n }`\n : result.ok\n ? `${paint.hint(marks.hint === '>' ? 'ok' : '\\u2714')} ${\n summary.errors + summary.warnings === 0\n ? 'the specification graph is consistent'\n : 'no errors - the specification graph holds'\n }`\n : `${paint.error(marks.error)} the specification graph is inconsistent`,\n );\n\n return lines.join('\\n');\n}\n\nfunction formatDiagnostic(\n diagnostic: Diagnostic,\n paint: Painter,\n marks: Glyphs,\n escalated: ReadonlySet<AnyRuleId>,\n): string[] {\n const mark = severityMark(diagnostic.severity, paint, marks);\n const label = escalated.has(diagnostic.rule)\n ? `${diagnostic.rule} ${paint.warn('(strict: warn -> error)')}`\n : diagnostic.rule;\n const lines: string[] = [\n `${mark} ${paint.location(formatRef(diagnostic.at))} ${paint.dim(label)}`,\n ` ${diagnostic.message}`,\n ];\n\n const width = Math.max(0, ...diagnostic.related.map((entry) => formatRef(entry.at).length));\n for (const entry of diagnostic.related) {\n const reference = formatRef(entry.at);\n lines.push(` ${paint.dim(marks.related)} ${paint.dim(reference.padEnd(width))} ${paint.dim(entry.note)}`);\n }\n\n lines.push(` ${paint.hint(marks.hint)} ${paint.hint(diagnostic.hint)}`);\n return lines;\n}\n\nfunction severityMark(severity: Exclude<Severity, 'off'>, paint: Painter, marks: Glyphs): string {\n switch (severity) {\n case 'error':\n return paint.error(marks.error);\n case 'warn':\n return paint.warn(marks.warn);\n case 'info':\n return paint.info(marks.info);\n }\n}\n\nfunction plural(count: number, word: string, plural?: string): string {\n if (count === 1) return word;\n return plural ?? `${word}s`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Markdown */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The same report as GitHub-flavoured Markdown.\n *\n * SARIF puts a finding on the line that caused it, which is where somebody\n * fixing one wants it. It says nothing to the person deciding whether to merge,\n * because a code-scanning alert is a list of lines and not a verdict. This is\n * the verdict: one table, the counts above it, and the baseline's slack\n * underneath, sized to be read without scrolling.\n *\n * Written for `$GITHUB_STEP_SUMMARY` and for a pull-request comment, but it is\n * named for what it is rather than for where it goes - the same text is what a\n * review tool, a chat message or a generated page wants.\n *\n * It carries no duration, which the JSON report does, so two runs over one\n * corpus produce identical bytes. That is what lets a test compare a run from\n * a subdirectory against a run from the root and assert they are the same\n * report rather than the same shape. See ADR-0015 and ADR-0018.\n */\nexport function formatMarkdown(result: AnalysisResult, options: ReporterOptions = {}): string {\n const { summary } = result;\n const escalated = options.escalated ?? EMPTY_RULES;\n const ratcheted = ratchetFailed(options.baseline);\n const lines: string[] = ['### spec-graph', ''];\n\n const verdict =\n ratcheted && result.ok\n ? 'The baseline is looser than the repository.'\n : result.ok\n ? summary.errors + summary.warnings === 0\n ? 'The specification graph is consistent.'\n : 'No errors - the specification graph holds.'\n : 'The specification graph is inconsistent.';\n lines.push(verdict, '');\n\n lines.push('| | |', '| --- | ---: |');\n lines.push(`| Documents | ${summary.documents} |`);\n lines.push(`| Items | ${summary.items} |`);\n lines.push(`| Relations | ${summary.edges} |`);\n lines.push(`| Open obligations | ${summary.openObligations} |`);\n lines.push(`| Errors | ${summary.errors} |`);\n lines.push(`| Warnings | ${summary.warnings} |`);\n lines.push(`| Notes | ${summary.infos} |`);\n lines.push('');\n\n const limit = options.max && options.max > 0 ? options.max : result.diagnostics.length;\n const shown = result.diagnostics.slice(0, limit);\n\n if (shown.length > 0) {\n lines.push('| | Rule | Where | Finding |', '| --- | --- | --- | --- |');\n for (const diagnostic of shown) {\n const rule = escalated.has(diagnostic.rule) ? `${diagnostic.rule} (strict)` : diagnostic.rule;\n // The hint in the same cell, under the message. A finding without its\n // next action is the half a reader cannot act on, and a fifth column\n // would push the message off the side of the page.\n const what = `${cell(diagnostic.message)}<br>${cell(diagnostic.hint)}`;\n lines.push(`| ${diagnostic.severity} | \\`${cell(rule)}\\` | \\`${cell(formatRef(diagnostic.at))}\\` | ${what} |`);\n }\n if (result.diagnostics.length > shown.length) {\n lines.push(`| | | | ... and ${result.diagnostics.length - shown.length} more |`);\n }\n lines.push('');\n }\n\n const baseline = options.baseline;\n if (baseline !== undefined) {\n const accepted = `${baseline.suppressed} ${plural(baseline.suppressed, 'finding')} accepted by \\`${cell(baseline.source)}\\``;\n if (baseline.stale === 0) {\n lines.push(accepted, '');\n } else {\n const gone = (baseline.entries ?? []).filter((entry) => entry.reason === 'gone').length;\n lines.push(\n `${accepted}, and ${baseline.stale} ${plural(baseline.stale, 'entry', 'entries')} no longer ${\n baseline.stale === 1 ? 'occurs' : 'occur'\n }${\n gone === 0\n ? ''\n : ` - ${gone} of them ${gone === 1 ? 'names a document' : 'name documents'} this run did not see`\n }.`,\n '',\n );\n // Listed rather than counted, because the point of a summary on a pull\n // request is that somebody can act on it without opening a terminal.\n lines.push('| Entry | Rule | Document | Why |', '| --- | --- | --- | --- |');\n for (const entry of baseline.entries ?? []) {\n const why = entry.reason === 'gone' ? 'not in this corpus - check the include patterns' : 'fixed';\n lines.push(`| ${entry.reason} | \\`${cell(entry.rule)}\\` | \\`${cell(entry.document)}\\` | ${why} |`);\n }\n lines.push('');\n }\n }\n\n if (options.verbose && result.problems.length > 0) {\n lines.push('<details><summary>Problems with the input</summary>', '');\n for (const problem of result.problems) {\n lines.push(`- \\`${cell(formatRef(problem.at))}\\` ${cell(problem.message)}`);\n }\n lines.push('', '</details>', '');\n }\n\n if (options.verbose && result.corpus.suppressed.length > 0) {\n lines.push('<details><summary>References this configuration silenced</summary>', '');\n for (const [target, entry] of groupSuppressed(result.corpus.suppressed)) {\n const where = entry.by === 'family' ? 'ignored family' : 'ignored reference';\n const times = entry.count === 1 ? '' : ` (${entry.count} times)`;\n lines.push(`- \\`${cell(target)}\\` - ${where}${times}, first at \\`${cell(formatRef(entry.at))}\\``);\n }\n lines.push('', '</details>', '');\n }\n\n return `${lines.join('\\n').replace(/\\n+$/, '')}\\n`;\n}\n\n/**\n * Makes one value safe to put in a table cell.\n *\n * A pipe would end the cell and a newline would end the row, and a diagnostic\n * message is written by whoever wrote the rule - including a project rule,\n * whose message is a template a repository controls.\n */\nfunction cell(value: string): string {\n return value.replace(/[|]/g, '&#124;').replace(/\\s+/g, ' ').trim();\n}\n\n/* -------------------------------------------------------------------------- */\n/* JSON */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The machine-readable report.\n *\n * Deliberately flat and versioned: this is the contract a CI annotator or a\n * dashboard builds against, and it must be safe to add fields to it later.\n */\n/**\n * One row per silenced target, with the first place it was written.\n *\n * Grouped because a concept tag used forty times is one decision, and forty\n * lines of it would bury the one entry somebody needs to see. Insertion order\n * is document order, which is already deterministic.\n */\nfunction groupSuppressed(\n suppressed: readonly SuppressedRef[],\n): Map<string, { at: SourceRef; by: SuppressedRef['by']; count: number }> {\n const out = new Map<string, { at: SourceRef; by: SuppressedRef['by']; count: number }>();\n for (const entry of suppressed) {\n const seen = out.get(entry.target);\n if (seen === undefined) out.set(entry.target, { at: entry.at, by: entry.by, count: 1 });\n else seen.count += 1;\n }\n return out;\n}\n\n/**\n * True when a baseline was asked to ratchet and has slack left in it.\n *\n * Both reporters ask, because both have to agree with the exit code: a report\n * that prints \"ok\" above a failing build is worse than no report.\n */\nfunction ratchetFailed(baseline: ReporterOptions['baseline']): boolean {\n return baseline !== undefined && baseline.ratchet === true && baseline.stale > 0;\n}\n\n/* -------------------------------------------------------------------------- */\n/* SARIF */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The static-analysis interchange format, for the tools that already read it.\n *\n * The reason to emit it is not the format, it is what consumes the format:\n * GitHub code scanning turns a SARIF upload into annotations on the diff, and\n * an editor turns it into the problems pane, neither of which needs a line of\n * spec-graph-specific integration.\n *\n * One field earns the whole exercise. `partialFingerprints` is how a consumer\n * tracks a finding across commits without keying on a line number, and\n * spec-graph already has exactly that identifier for exactly that reason - the\n * `rule/document/subject` triple a baseline is keyed on (ADR-0012). The two\n * problems turned out to be the same problem, so the answer is the same answer.\n *\n * Deterministic and timestamp-free, like every other output here. Nothing about\n * a run that has the same findings should produce a different file.\n */\nexport function formatSarif(\n result: AnalysisResult,\n graph: SpecGraph,\n options: {\n version?: string | undefined;\n escalated?: ReadonlySet<AnyRuleId> | undefined;\n projectRules?: readonly ProjectRule[] | undefined;\n } = {},\n): string {\n const escalated = options.escalated ?? EMPTY_RULES;\n // A project rule describes itself by the selector it is, because that is the\n // only honest answer: its message is a template, and a template with `{0}` in\n // it is not a description of anything. See ADR-0016.\n const known: [AnyRuleId, string, Severity][] = [\n ...RULE_IDS.map((id): [AnyRuleId, string, Severity] => [id, RULE_DESCRIPTIONS[id], DEFAULT_SEVERITIES[id]]),\n ...(options.projectRules ?? []).map((rule): [AnyRuleId, string, Severity] => [\n rule.id,\n rule.sources.join(' | '),\n rule.severity,\n ]),\n ];\n const fired = known.filter(([id]) => result.diagnostics.some((diagnostic) => diagnostic.rule === id));\n return `${JSON.stringify(\n {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: 'spec-graph',\n informationUri: 'https://github.com/DescentVTT/spec-graph',\n ...(options.version === undefined ? {} : { version: options.version, semanticVersion: options.version }),\n // Only the rules that fired. A driver listing all of them\n // describes the tool; this file describes the run.\n rules: fired.map(([id, description, level]) => ({\n id,\n shortDescription: { text: description },\n defaultConfiguration: { level: sarifLevel(level) },\n })),\n },\n },\n results: result.diagnostics.map((diagnostic) => {\n const print = fingerprintOf(graph, diagnostic);\n return {\n ruleId: diagnostic.rule,\n level: sarifLevel(diagnostic.severity),\n message: { text: `${diagnostic.message}. ${diagnostic.hint}` },\n locations: [sarifLocation(diagnostic.at)],\n ...(diagnostic.related.length === 0\n ? {}\n : {\n relatedLocations: diagnostic.related.map((entry) => ({\n ...sarifLocation(entry.at),\n message: { text: entry.note },\n })),\n }),\n partialFingerprints: {\n specGraphIdentity: `${diagnostic.rule}/${print.document}/${print.subject}`,\n },\n properties: {\n nodes: diagnostic.nodes,\n target: diagnostic.target,\n // A finding that is only an error because of a flag says so\n // here too, so a reviewer reading an annotation is not misled.\n escalated: escalated.has(diagnostic.rule),\n },\n };\n }),\n },\n ],\n },\n null,\n 2,\n )}\\n`;\n}\n\nfunction sarifLevel(severity: Severity): string {\n switch (severity) {\n case 'error':\n return 'error';\n case 'warn':\n return 'warning';\n case 'info':\n return 'note';\n default:\n return 'none';\n }\n}\n\nfunction sarifLocation(at: SourceRef): {\n physicalLocation: {\n artifactLocation: { uri: string };\n region: { startLine: number; startColumn: number; endLine: number; endColumn: number };\n };\n} {\n return {\n physicalLocation: {\n // Already repository-relative and POSIX, which is what SARIF asks for.\n artifactLocation: { uri: at.file },\n region: {\n startLine: at.span.start.line,\n startColumn: at.span.start.column,\n endLine: at.span.end.line,\n endColumn: at.span.end.column,\n },\n },\n };\n}\n\nexport function formatJson(\n result: AnalysisResult,\n options: { escalated?: ReadonlySet<AnyRuleId>; baseline?: ReporterOptions['baseline'] } = {},\n): string {\n const escalated = options.escalated ?? EMPTY_RULES;\n return `${JSON.stringify(\n {\n version: 1,\n ok: result.ok && !ratchetFailed(options.baseline),\n strict: escalated.size > 0,\n ...(options.baseline === undefined ? {} : { baseline: options.baseline }),\n summary: result.summary,\n files: result.files,\n // The audit trail for what configuration silenced. Always present, unlike\n // the human report's --verbose gate: a machine reader that has to ask for\n // it twice will not ask. See ADR-0008.\n suppressed: result.corpus.suppressed.map((entry) => ({\n target: entry.target,\n from: entry.from,\n by: entry.by,\n file: entry.at.file,\n line: entry.at.span.start.line,\n })),\n diagnostics: result.diagnostics.map((diagnostic) => ({\n rule: diagnostic.rule,\n severity: diagnostic.severity,\n // True when this finding is only an error because of --strict.\n escalated: escalated.has(diagnostic.rule),\n message: diagnostic.message,\n hint: diagnostic.hint,\n nodes: diagnostic.nodes,\n target: diagnostic.target,\n file: diagnostic.at.file,\n line: diagnostic.at.span.start.line,\n column: diagnostic.at.span.start.column,\n endLine: diagnostic.at.span.end.line,\n endColumn: diagnostic.at.span.end.column,\n related: diagnostic.related.map((entry) => ({\n file: entry.at.file,\n line: entry.at.span.start.line,\n column: entry.at.span.start.column,\n note: entry.note,\n })),\n })),\n problems: result.problems.map((problem) => ({\n message: problem.message,\n file: problem.at.file,\n line: problem.at.span.start.line,\n })),\n },\n null,\n 2,\n )}\\n`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Graph export */\n/* -------------------------------------------------------------------------- */\n\nexport type GraphFormat = 'dot' | 'mermaid' | 'json';\n\nexport interface GraphExportOptions {\n /** Leave out `contains` edges and item nodes. */\n readonly documentsOnly?: boolean | undefined;\n /**\n * What made the export, for the JSON form. Passed in rather than looked up,\n * because reading the package's own version is I/O and this module has none.\n * Two exports from different versions differ wherever extraction changed, and\n * `diff` warns about that only if it can see it (ADR-0020).\n */\n readonly generator?: { readonly name: string; readonly version: string } | undefined;\n}\n\n/** Serialises the graph for Graphviz, Mermaid, or a downstream tool. */\nexport function formatGraph(graph: SpecGraph, format: GraphFormat, options: GraphExportOptions = {}): string {\n const skipItems = options.documentsOnly ?? false;\n const nodes = [...graph.nodes.values()].filter((node) => !skipItems || node.kind === 'document');\n const visible = new Set(nodes.map((node) => node.id));\n\n // Hiding items must not hide what they say. An obligation delegated from an\n // item to a document is lifted onto the item's owner, so the document-level\n // view still shows the handover rather than silently losing it.\n const lifted = skipItems\n ? dedupeEdges(\n graph.edges\n // Containment of an *item* is what hiding items makes redundant.\n // Containment of a specification by the register that holds it is\n // structure between documents, and is what this view exists to show.\n .filter((edge) => edge.kind !== 'contains' || visible.has(edge.to))\n .map((edge) => {\n const from = graph.owningDocument(edge.from)?.id ?? edge.from;\n const to = graph.owningDocument(edge.to)?.id ?? edge.to;\n return from === edge.from && to === edge.to ? edge : { ...edge, from, to, reflexive: from === to };\n })\n .filter((edge) => !edge.reflexive),\n )\n : graph.edges;\n\n const edges = lifted.filter((edge) => visible.has(edge.from) && visible.has(edge.to));\n\n switch (format) {\n case 'dot':\n return toDot(nodes, edges);\n case 'mermaid':\n return toMermaid(nodes, edges);\n case 'json':\n return `${JSON.stringify(\n {\n version: 1,\n ...(options.generator !== undefined && { generator: options.generator }),\n nodes: nodes.map(serialiseNode),\n edges: edges.map((edge) => ({\n kind: edge.kind,\n from: edge.from,\n to: edge.to,\n origin: edge.origin,\n declaredIn: edge.declaredIn,\n file: edge.declaredAt.file,\n line: edge.declaredAt.span.start.line,\n })),\n },\n null,\n 2,\n )}\\n`;\n }\n}\n\n/** Collapses duplicate relations produced by lifting item edges onto documents. */\nfunction dedupeEdges(edges: readonly Edge[]): Edge[] {\n const seen = new Set<string>();\n const out: Edge[] = [];\n for (const edge of edges) {\n const key = `${edge.kind} ${edge.from} ${edge.to}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(edge);\n }\n return out;\n}\n\nfunction serialiseNode(node: SpecNode): Record<string, unknown> {\n const base = {\n id: node.id,\n kind: node.kind,\n title: node.title,\n file: node.at.file,\n line: node.at.span.start.line,\n };\n return node.kind === 'document'\n ? { ...base, path: node.path, phase: node.phase, status: node.rawStatus, aliases: node.aliases }\n : {\n ...base,\n declared: node.declared,\n document: node.document,\n section: node.section,\n disposition: node.disposition,\n openness: node.openness,\n };\n}\n\n/** Phase colours, chosen to stay legible in both light and dark renderings. */\nconst PHASE_FILL: Readonly<Record<string, string>> = {\n draft: '#e8f0fe',\n active: '#e6f4ea',\n frozen: '#e8eaed',\n retired: '#fce8e6',\n record: '#f3e8fd',\n unknown: '#ffffff',\n};\n\nfunction toDot(nodes: readonly SpecNode[], edges: readonly Edge[]): string {\n const lines = ['digraph spec {', ' rankdir=LR;', ' node [shape=box, style=\"rounded,filled\", fontname=\"sans\"];'];\n for (const node of nodes) {\n const fill = node.kind === 'document' ? (PHASE_FILL[node.phase] ?? '#ffffff') : '#fffbe6';\n const label = node.kind === 'document' ? `${node.id}\\\\n${escapeDot(node.title)}` : escapeDot(node.text);\n const shape = node.kind === 'document' ? 'box' : 'note';\n lines.push(` \"${escapeDot(node.id)}\" [label=\"${label}\", fillcolor=\"${fill}\", shape=${shape}];`);\n }\n for (const edge of edges) {\n const style = edge.kind === 'contains' ? ', style=dotted' : '';\n lines.push(` \"${escapeDot(edge.from)}\" -> \"${escapeDot(edge.to)}\" [label=\"${edge.kind}\"${style}];`);\n }\n lines.push('}');\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction toMermaid(nodes: readonly SpecNode[], edges: readonly Edge[]): string {\n const lines = ['graph LR'];\n const alias = new Map<string, string>();\n nodes.forEach((node, position) => alias.set(node.id, `n${position}`));\n\n for (const node of nodes) {\n const key = alias.get(node.id) as string;\n const label = escapeMermaid(node.kind === 'document' ? node.id : node.text);\n lines.push(node.kind === 'document' ? ` ${key}[\"${label}\"]` : ` ${key}([\"${label}\"])`);\n if (node.kind === 'document' && node.phase !== 'unknown') lines.push(` class ${key} ${node.phase};`);\n }\n for (const edge of edges) {\n const from = alias.get(edge.from);\n const to = alias.get(edge.to);\n if (!from || !to) continue;\n lines.push(` ${from} -->|${edge.kind}| ${to}`);\n }\n for (const [phase, fill] of Object.entries(PHASE_FILL)) {\n if (phase === 'unknown') continue;\n lines.push(` classDef ${phase} fill:${fill},stroke:#5f6368;`);\n }\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction escapeDot(value: string): string {\n return value.replace(/[\"\\\\]/g, '\\\\$&').replace(/\\n/g, '\\\\n');\n}\n\nfunction escapeMermaid(value: string): string {\n return value.replace(/[\"#]/g, ' ').replace(/\\s+/g, ' ').trim();\n}\n"]}
package/dist/resolve.js CHANGED
@@ -39,6 +39,17 @@ export function resolveCorpus(extracted, options = {}) {
39
39
  nodes.set(entry.document.id, entry.document);
40
40
  documents.push(entry.document);
41
41
  for (const item of entry.items) {
42
+ // Nodes are keyed by id, so a second item would replace the first in the
43
+ // graph while both were still counted, and one of them would vanish from
44
+ // the export without a word.
45
+ const taken = nodes.get(item.id);
46
+ if (taken) {
47
+ problems.push({
48
+ message: `duplicate item id "${item.id}", already taken at ${taken.at.file}:${taken.at.span.start.line}`,
49
+ at: item.at,
50
+ });
51
+ continue;
52
+ }
42
53
  nodes.set(item.id, item);
43
54
  items.push(item);
44
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Corpus-level reference resolution - the foreign-key check.\n *\n * Extraction produces relations whose targets are still just text. This module\n * turns each into an edge or into an explicit, reportable failure. The whole\n * value of the exercise is in refusing to do either job carelessly:\n *\n * - **A deliberate reference that does not resolve is an error.** A link, a\n * front-matter field or a directive naming a document that does not exist is\n * a broken foreign key, and silence about it is how reference graphs rot.\n * - **An opportunistic reference that does not resolve is nothing.** `ADR-0007`\n * written in prose is a citation; `SHA-256` is not. Since the two are\n * indistinguishable in isolation, bare identifiers are only reported when\n * their family already exists in the corpus - so `ADR-0099` in a repository\n * full of ADRs is a finding, and `T-1000` in the same repository is not.\n * - **Two candidates is worse than none.** A reference that matches several\n * documents is reported as ambiguous rather than silently bound to whichever\n * one happened to be indexed first.\n */\n\nimport type { ExtractedDocument, ReferenceCandidate } from './extract.js';\nimport {\n isDocumentTarget,\n isExternal,\n looksLikePath,\n normaliseRef,\n parseBareRef,\n parsePrefixedRef,\n splitAnchor,\n withinOneEdit,\n} from './identity.js';\nimport { basenamePosix, dirnamePosix, extnamePosix, resolveFrom } from './paths.js';\nimport type {\n DanglingRef,\n DocumentNode,\n Edge,\n ItemNode,\n MisreadKey,\n ParseProblem,\n SpecNode,\n SuppressedRef,\n} from './types.js';\n\nexport interface ResolveOptions {\n /**\n * Whether a repository-relative path exists on disk.\n *\n * Used only to tell \"you linked to a file that is not a specification\" apart\n * from \"you linked to nothing at all\", which are different mistakes with\n * different fixes.\n */\n readonly fileExists?: ((path: string) => boolean) | undefined;\n /**\n * Targets whose failure to resolve should not be reported.\n *\n * This is a *suppression* filter, not a resolution one: it is consulted only\n * when a reference has already failed to resolve. A reference that resolves\n * still becomes an edge no matter what this says, so no amount of\n * configuration can silently delete a relation from the graph.\n */\n readonly isIgnoredReference?: ((target: string) => boolean) | undefined;\n /**\n * Families that are never citations in this repository.\n *\n * `RFC 2119` is the canonical case: every specification cites it, and a\n * repository that keeps its own `RFC-*` documents will otherwise read that\n * sentence as a dangling reference to a local RFC 2119 it does not have.\n * Consulted only after resolution has failed, like every other filter here.\n */\n readonly isIgnoredFamily?: ((family: string) => boolean) | undefined;\n}\n\nexport interface ResolvedCorpus {\n readonly nodes: ReadonlyMap<string, SpecNode>;\n readonly documents: readonly DocumentNode[];\n readonly items: readonly ItemNode[];\n readonly edges: readonly Edge[];\n readonly dangling: readonly DanglingRef[];\n readonly problems: readonly ParseProblem[];\n readonly misreadKeys: readonly MisreadKey[];\n /**\n * References this repository declared none of its business.\n *\n * Not findings, and never reported as such - they are the audit trail for\n * the two settings that can silence one. See ADR-0008.\n */\n readonly suppressed: readonly SuppressedRef[];\n}\n\ninterface Index {\n readonly byId: Map<string, string>;\n readonly byAlias: Map<string, Set<string>>;\n /** The literal path of a file. Unique: no two files share one. */\n readonly byPath: Map<string, string>;\n /**\n * Spellings that address a file without naming it exactly - the extension\n * dropped, a directory standing for its README. Several files can answer to\n * one of those, so this is a set, exactly as `byAlias` is.\n */\n readonly byPathAlias: Map<string, Set<string>>;\n readonly byFamilyNumber: Map<string, Set<string>>;\n readonly families: Set<string>;\n /** Every file by the directory holding it, for a basename that was mistyped. */\n readonly byDirectory: Map<string, { stem: string; id: string }[]>;\n /**\n * Alias keys grouped by length.\n *\n * A one-edit match can only differ in length by one, so this turns the scan\n * behind a suggestion from the whole corpus into three buckets of it.\n */\n readonly aliasesByLength: Map<number, string[]>;\n readonly anchors: Map<string, ReadonlySet<string>>;\n readonly itemIds: Set<string>;\n readonly familyOf: Map<string, string | null>;\n}\n\n/** Resolves every extracted reference against the whole corpus. */\nexport function resolveCorpus(\n extracted: readonly ExtractedDocument[],\n options: ResolveOptions = {},\n): ResolvedCorpus {\n const index = buildIndex(extracted);\n const nodes = new Map<string, SpecNode>();\n const documents: DocumentNode[] = [];\n const items: ItemNode[] = [];\n const problems: ParseProblem[] = [];\n const misreadKeys: MisreadKey[] = [];\n\n for (const entry of extracted) {\n const existing = nodes.get(entry.document.id);\n if (existing && existing.kind === 'document') {\n problems.push({\n message: `duplicate document id \"${entry.document.id}\", already declared by ${existing.path}`,\n at: entry.document.at,\n });\n continue;\n }\n nodes.set(entry.document.id, entry.document);\n documents.push(entry.document);\n for (const item of entry.items) {\n nodes.set(item.id, item);\n items.push(item);\n }\n problems.push(...entry.problems);\n misreadKeys.push(...entry.misreadKeys);\n }\n\n const edges: Edge[] = [];\n const dangling: DanglingRef[] = [];\n const suppressed: SuppressedRef[] = [];\n const byKey = new Map<string, number>();\n\n // Structural edges: a register contains the specifications written inside it.\n for (const entry of extracted) {\n if (entry.containerId === null) continue;\n if (!nodes.has(entry.containerId) || !nodes.has(entry.document.id)) continue;\n edges.push({\n kind: 'contains',\n from: entry.containerId,\n to: entry.document.id,\n origin: 'structural',\n declaredAt: entry.document.at,\n raw: entry.document.title,\n declaredIn: [entry.document.at.file],\n reflexive: false,\n });\n }\n\n // Structural edges: a document contains its items.\n for (const item of items) {\n edges.push({\n kind: 'contains',\n from: item.document,\n to: item.id,\n origin: 'structural',\n declaredAt: item.at,\n raw: item.text,\n declaredIn: [item.at.file],\n reflexive: false,\n });\n }\n\n for (const entry of extracted) {\n for (const candidate of entry.references) {\n if (!nodes.has(candidate.from)) continue;\n const outcome = resolveOne(candidate, entry, index, nodes, options);\n if (outcome === null) continue;\n if ('by' in outcome) {\n suppressed.push(outcome);\n continue;\n }\n if ('reason' in outcome) {\n dangling.push(outcome);\n continue;\n }\n // Collapse duplicates: the same relation stated twice is one edge - but\n // every declaration site is kept, because a supersession recorded in only\n // one of the two documents is itself a finding.\n const key = `${outcome.kind} ${outcome.from} ${outcome.to}`;\n const existing = byKey.get(key);\n if (existing !== undefined) {\n const previous = edges[existing] as Edge;\n if (!previous.declaredIn.includes(outcome.declaredAt.file)) {\n edges[existing] = { ...previous, declaredIn: [...previous.declaredIn, outcome.declaredAt.file] };\n }\n continue;\n }\n byKey.set(key, edges.length);\n edges.push(outcome);\n }\n }\n\n return { nodes, documents, items, edges, dangling, problems, misreadKeys, suppressed };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Indexing */\n/* -------------------------------------------------------------------------- */\n\nfunction buildIndex(extracted: readonly ExtractedDocument[]): Index {\n const index: Index = {\n byId: new Map(),\n byAlias: new Map(),\n byPath: new Map(),\n byPathAlias: new Map(),\n byFamilyNumber: new Map(),\n families: new Set(),\n byDirectory: new Map(),\n aliasesByLength: new Map(),\n anchors: new Map(),\n itemIds: new Set(),\n familyOf: new Map(),\n };\n\n for (const entry of extracted) {\n const id = entry.document.id;\n index.byId.set(normaliseRef(id), id);\n index.anchors.set(id, entry.anchors);\n index.familyOf.set(id, entry.identity.family);\n\n for (const alias of entry.document.aliases) {\n const set = index.byAlias.get(alias) ?? new Set<string>();\n set.add(id);\n index.byAlias.set(alias, set);\n }\n\n // Only a file answers to its path. A region keeps the path on its node, so a\n // finding can say where it lives and `document[path=...]` can select it, but\n // it must not be reachable *by* that path: two nodes answering to one path\n // makes every link to the file ambiguous, and this index resolves a\n // collision by keeping whichever was written last. A link to a file holding\n // a register bound to its final row, quietly and with no diagnostic, and\n // anchors were then checked against that row's span rather than the file's.\n // ADR-0009 said a region does not claim the file's path; this is the index\n // where that had to be true.\n if (entry.containerId === null) {\n const path = entry.document.path.toLowerCase();\n index.byPath.set(path, id);\n for (const spelling of pathAliases(entry.document.path)) {\n const set = index.byPathAlias.get(spelling) ?? new Set<string>();\n set.add(id);\n index.byPathAlias.set(spelling, set);\n }\n const directory = dirnamePosix(path);\n const siblings = index.byDirectory.get(directory) ?? [];\n siblings.push({ stem: stemOf(path), id });\n index.byDirectory.set(directory, siblings);\n }\n\n if (entry.identity.family !== null && entry.identity.number !== null) {\n index.families.add(entry.identity.family);\n const key = `${entry.identity.family}:${entry.identity.number}`;\n const set = index.byFamilyNumber.get(key) ?? new Set<string>();\n set.add(id);\n index.byFamilyNumber.set(key, set);\n }\n\n for (const item of entry.items) index.itemIds.add(item.id);\n }\n\n for (const alias of index.byAlias.keys()) {\n const bucket = index.aliasesByLength.get(alias.length) ?? [];\n bucket.push(alias);\n index.aliasesByLength.set(alias.length, bucket);\n }\n\n return index;\n}\n\n/** A file name with its extension taken off: `docs/a/0004-sharding.md` -> `0004-sharding`. */\nfunction stemOf(path: string): string {\n const base = basenamePosix(path);\n return base.slice(0, base.length - extnamePosix(base).length);\n}\n\n/** Every spelling of a path that addresses a file without naming it exactly. */\nfunction pathAliases(path: string): string[] {\n const keys = new Set<string>();\n const extension = extnamePosix(path);\n if (extension.length > 0) keys.add(path.slice(0, path.length - extension.length).toLowerCase());\n // `docs/adr/0007/README.md` is also addressed as `docs/adr/0007`.\n const base = basenamePosix(path);\n if (/^(readme|index)\\./i.test(base)) {\n const parent = path.slice(0, path.length - base.length - 1);\n if (parent.length > 0) keys.add(parent.toLowerCase());\n }\n // A file never addresses itself inexactly. Leaving this in would let a\n // contrived name - `docs/a.md.md`, whose stem is another file's whole path -\n // make an exact link look ambiguous.\n keys.delete(path.toLowerCase());\n return [...keys];\n}\n\n/* -------------------------------------------------------------------------- */\n/* Resolution */\n/* -------------------------------------------------------------------------- */\n\nfunction resolveOne(\n candidate: ReferenceCandidate,\n entry: ExtractedDocument,\n index: Index,\n nodes: ReadonlyMap<string, SpecNode>,\n options: ResolveOptions,\n): Edge | DanglingRef | SuppressedRef | null {\n const { target: bare, anchor } = splitAnchor(candidate.target);\n\n // A pure `#anchor` points inside the citing document.\n if (bare.length === 0 && anchor !== null) {\n return bindAnchor(candidate, entry.document.id, anchor, index, nodes, options);\n }\n\n if (isExternal(bare)) return null;\n // A link to source code, an image or a config file is not a specification\n // reference. Validating it would report an error on the most ordinary thing a\n // design document does.\n if (!isDocumentTarget(bare)) return null;\n\n const found = lookup(bare, entry, index);\n\n if (found.ids.length === 0) {\n if (candidate.opportunistic && !worthReporting(bare, index)) return null;\n const silenced = filteredBy(candidate.target, bare, options);\n if (silenced !== null) return suppression(candidate, silenced);\n // A trailing slash names a directory. Linking to one is ordinary - \"the\n // decisions live in [archive/](archive/)\" - and is not a citation of any\n // document. Resolution is still attempted first, so a directory-style\n // document written as `0007-sharding/` continues to resolve.\n if (bare.endsWith('/')) return null;\n const reason = pathMissingReason(bare, entry, options);\n return dangle(candidate, reason, found.near);\n }\n\n if (found.ids.length > 1) {\n if (candidate.opportunistic) return null;\n const silenced = filteredBy(candidate.target, bare, options);\n if (silenced !== null) return suppression(candidate, silenced);\n return dangle(candidate, 'ambiguous', found.ids);\n }\n\n const documentId = found.ids[0] as string;\n\n // A document naming itself in prose - almost always its own H1, `# ADR-0007:\n // Sharding` - is not a citation. Deliberate self-links are kept, because a\n // link that points at its own document is a real mistake worth reporting.\n if (candidate.opportunistic && documentId === entry.document.id) return null;\n\n if (anchor !== null) return bindAnchor(candidate, documentId, anchor, index, nodes, options);\n\n return makeEdge(candidate, documentId);\n}\n\ninterface Lookup {\n readonly ids: readonly string[];\n /** Near-misses worth suggesting in the report. */\n readonly near: readonly string[];\n}\n\n/**\n * The same path with its percent-escapes read.\n *\n * `[Design](docs/my%20design.md)` is what a renderer, a documentation site and\n * GitHub's own \"copy link\" all produce for a file with a space in its name, and\n * it names a real file. Returns `null` when there was nothing to decode or when\n * the escapes are malformed - `100%` in a path is not an escape sequence, and\n * `decodeURIComponent` throws on it.\n */\nfunction percentDecoded(target: string): string | null {\n if (!target.includes('%')) return null;\n try {\n const decoded = decodeURIComponent(target);\n return decoded === target ? null : decoded;\n } catch {\n return null;\n }\n}\n\nfunction lookup(target: string, entry: ExtractedDocument, index: Index): Lookup {\n const exact = lookupExact(target, entry, index);\n if (exact.length > 0) return { ids: exact, near: [] };\n // Tried second and never first, so a repository holding a file whose name\n // genuinely contains a percent escape keeps resolving by its written spelling.\n const decoded = percentDecoded(target);\n const relaxed = decoded === null ? [] : lookupExact(decoded, entry, index);\n if (relaxed.length > 0) return { ids: relaxed, near: [] };\n // Suggestions are computed only once resolution has failed outright, so their\n // cost is bounded by the number of findings rather than by the corpus.\n return { ids: [], near: nearMisses(target, entry, index) };\n}\n\nfunction lookupExact(target: string, entry: ExtractedDocument, index: Index): readonly string[] {\n if (looksLikePath(target)) {\n const resolved = resolveFrom(entry.document.path, target).toLowerCase();\n // Naming the file exactly is never ambiguous, whatever else is spelled the\n // same way.\n const byPath = index.byPath.get(resolved);\n if (byPath) return [byPath];\n // An inexact spelling can belong to more than one file: `docs/A` is both\n // `docs/A.md` with its extension dropped and `docs/A/README.md` standing\n // for its directory. Handing back every claimant makes that an\n // ambiguous-reference the author can settle, rather than a silent pick of\n // whichever happened to be indexed last.\n const spelled = index.byPathAlias.get(resolved);\n if (spelled && spelled.size > 0) return [...spelled];\n // A path may still be spelled as an identifier in a nested folder layout.\n const stem = basenamePosix(resolved);\n const byStem = index.byAlias.get(normaliseRef(stem.replace(/\\.[^.]+$/, '')));\n if (byStem && byStem.size > 0) return [...byStem];\n return [];\n }\n\n const key = normaliseRef(target);\n if (key.length === 0) return [];\n\n const byId = index.byId.get(key);\n if (byId) return [byId];\n\n const byAlias = index.byAlias.get(key);\n if (byAlias && byAlias.size > 0) return [...byAlias];\n\n const prefixed = parsePrefixedRef(target);\n if (prefixed) {\n const byFamily = index.byFamilyNumber.get(`${prefixed.family}:${prefixed.number}`);\n if (byFamily && byFamily.size > 0) return [...byFamily];\n return [];\n }\n\n // A bare number resolves only inside the citing document's own family. A\n // repository with both `adr/0007` and `rfc/0007` is ordinary, and guessing\n // between them would be worse than reporting nothing.\n const number = parseBareRef(target);\n if (number !== null) {\n const family = index.familyOf.get(entry.document.id) ?? null;\n if (family === null) return [];\n const byFamily = index.byFamilyNumber.get(`${family}:${number}`);\n if (byFamily && byFamily.size > 0) return [...byFamily];\n }\n\n return [];\n}\n\n/* -------------------------------------------------------------------------- */\n/* Near misses */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The one document a failed reference was probably meant to name.\n *\n * A suggestion is cheap to read and expensive to get wrong: \"did you mean\n * ADR-0008?\" against a citation that meant ADR-0012 sends a reader to the wrong\n * decision with a confidence nobody earned. So the bar is not closeness, it is\n * closeness *in the part of the spelling that is not the identity*. A family\n * name is a word people misremember. A number is the identity itself, and\n * `ADR-0009` sits one edit from every neighbour it has - so numbers are never\n * guessed at, and a repository of fifteen ADRs citing a sixteenth is told the\n * plain truth instead.\n *\n * Two gates, plus a fallback:\n *\n * - a path in the right directory whose basename is one edit out - a typo;\n * - a family one edit out with its number intact - `ARD-0009` for `ADR-0009`.\n *\n * Anything else falls through to a one-edit match against the folded spellings\n * documents already answer to, which is where a mistyped slug or wiki name\n * lands.\n *\n * There is deliberately no gate for a file that moved. Resolution already binds\n * a path by its basename, so `../guides/onboarding.md` finds the document that\n * is now in `handbook/` without anybody being asked to confirm a guess - and a\n * suggestion nobody needs is a suggestion that can only be wrong.\n *\n * Every gate ends the same way: **exactly one** candidate, or nothing. Two\n * suggestions is the ambiguity this module refuses to resolve anywhere else,\n * and the tail of a hint is no place to start.\n */\nfunction nearMisses(target: string, entry: ExtractedDocument, index: Index): string[] {\n if (looksLikePath(target)) {\n const resolved = resolveFrom(entry.document.path, target).toLowerCase();\n const stem = stemOf(resolved);\n const siblings = index.byDirectory.get(dirnamePosix(resolved)) ?? [];\n return sole(siblings.filter((file) => withinOneEdit(file.stem, stem)).map((file) => file.id));\n }\n\n const prefixed = parsePrefixedRef(target);\n if (prefixed !== null) {\n const hits: string[] = [];\n for (const family of index.families) {\n // The family as written needs no exclusion: one edit is never zero edits.\n if (!withinOneEdit(family.toLowerCase(), prefixed.family.toLowerCase())) continue;\n for (const id of index.byFamilyNumber.get(`${family}:${prefixed.number}`) ?? []) hits.push(id);\n }\n return sole(hits);\n }\n\n // A bare `12` carries nothing but a number, which is the one thing this\n // refuses to guess at.\n if (parseBareRef(target) !== null) return [];\n\n const key = normaliseRef(target);\n if (key.length < MIN_SUGGESTIBLE) return [];\n const hits: string[] = [];\n for (const length of [key.length - 1, key.length, key.length + 1]) {\n for (const alias of index.aliasesByLength.get(length) ?? []) {\n if (!withinOneEdit(alias, key)) continue;\n for (const id of index.byAlias.get(alias) ?? []) hits.push(id);\n }\n }\n return sole(hits);\n}\n\n/**\n * How long a folded spelling has to be before one edit means anything.\n *\n * Below six characters an edit is most of the word, and every corpus is full of\n * short names that differ by exactly that much.\n */\nconst MIN_SUGGESTIBLE = 6;\n\n/** The candidates, if there is exactly one of them. Otherwise nothing. */\nfunction sole(ids: Iterable<string>): string[] {\n const unique = new Set(ids);\n return unique.size === 1 ? [...unique] : [];\n}\n\n/**\n * Which setting, if any, declared this reference none of the repository's\n * business.\n *\n * Returns the mechanism rather than a boolean so the audit trail can say which\n * line of configuration to go and look at. A team that silenced eight things\n * with one glob and one with a family needs to be told them apart.\n */\nfunction filteredBy(target: string, bare: string, options: ResolveOptions): SuppressedRef['by'] | null {\n if (options.isIgnoredReference?.(target)) return 'reference';\n const prefixed = parsePrefixedRef(bare);\n if (prefixed !== null && options.isIgnoredFamily?.(prefixed.family) === true) return 'family';\n return null;\n}\n\n/**\n * Whether an unresolved bare identifier deserves a report.\n *\n * Only when the corpus already contains that family. `ADR-0099` in a repository\n * of ADRs is a real dangling citation; `T-1000` in the same repository is a\n * sentence about a robot.\n */\nfunction worthReporting(target: string, index: Index): boolean {\n const prefixed = parsePrefixedRef(target);\n return prefixed !== null && index.families.has(prefixed.family);\n}\n\nfunction pathMissingReason(\n target: string,\n entry: ExtractedDocument,\n options: ResolveOptions,\n): DanglingRef['reason'] {\n if (!looksLikePath(target) || !options.fileExists) return 'unknown-target';\n const resolved = resolveFrom(entry.document.path, target);\n return options.fileExists(resolved) ? 'not-a-spec' : 'unknown-target';\n}\n\n/**\n * Binds a `#anchor` to an item or a section.\n *\n * Anchors are how a delegation names a specific obligation rather than a whole\n * document, so resolving them precisely is what lets a ghost-handover finding\n * say *which* question was handed into the archive.\n */\nfunction bindAnchor(\n candidate: ReferenceCandidate,\n documentId: string,\n anchor: string,\n index: Index,\n nodes: ReadonlyMap<string, SpecNode>,\n options: ResolveOptions,\n): Edge | DanglingRef | SuppressedRef | null {\n const itemId = `${documentId}#${anchor}`;\n if (index.itemIds.has(itemId)) return makeEdge(candidate, itemId);\n\n const anchors = index.anchors.get(documentId);\n if (anchors?.has(anchor.toLowerCase())) return makeEdge(candidate, documentId);\n\n // Some renderers slugify differently; try the loosest reasonable match before\n // calling it broken.\n const loose = anchor.toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, '-').replace(/^-|-$/g, '');\n if (anchors?.has(loose)) return makeEdge(candidate, documentId);\n\n const silenced = filteredBy(candidate.target, splitAnchor(candidate.target).target, options);\n if (silenced !== null) return suppression(candidate, silenced);\n\n const candidates = [...(nodes.keys() as Iterable<string>)].filter(\n (id) => id.startsWith(`${documentId}#`) && id.toLowerCase().includes(loose),\n );\n return {\n kind: candidate.kind,\n from: candidate.from,\n target: candidate.target,\n reason: 'unknown-anchor',\n origin: candidate.origin,\n declaredAt: candidate.declaredAt,\n raw: candidate.raw,\n candidates,\n };\n}\n\nfunction makeEdge(candidate: ReferenceCandidate, resolved: string): Edge {\n const from = candidate.inverted ? resolved : candidate.from;\n const to = candidate.inverted ? candidate.from : resolved;\n return {\n kind: candidate.kind,\n from,\n to,\n origin: candidate.origin,\n declaredAt: candidate.declaredAt,\n raw: candidate.raw,\n declaredIn: [candidate.declaredAt.file],\n reflexive: documentOf(from) === documentOf(to),\n };\n}\n\nfunction suppression(candidate: ReferenceCandidate, by: SuppressedRef['by']): SuppressedRef {\n return { target: candidate.target, from: candidate.from, at: candidate.declaredAt, by };\n}\n\nfunction dangle(\n candidate: ReferenceCandidate,\n reason: DanglingRef['reason'],\n candidates: readonly string[],\n): DanglingRef {\n return {\n kind: candidate.kind,\n from: candidate.from,\n target: candidate.target,\n reason,\n origin: candidate.origin,\n declaredAt: candidate.declaredAt,\n raw: candidate.raw,\n candidates,\n };\n}\n\n/** The document part of a node id: `ADR-7#q.1` -> `ADR-7`. */\nexport function documentOf(nodeId: string): string {\n const hash = nodeId.indexOf('#');\n return hash === -1 ? nodeId : nodeId.slice(0, hash);\n}\n"]}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Corpus-level reference resolution - the foreign-key check.\n *\n * Extraction produces relations whose targets are still just text. This module\n * turns each into an edge or into an explicit, reportable failure. The whole\n * value of the exercise is in refusing to do either job carelessly:\n *\n * - **A deliberate reference that does not resolve is an error.** A link, a\n * front-matter field or a directive naming a document that does not exist is\n * a broken foreign key, and silence about it is how reference graphs rot.\n * - **An opportunistic reference that does not resolve is nothing.** `ADR-0007`\n * written in prose is a citation; `SHA-256` is not. Since the two are\n * indistinguishable in isolation, bare identifiers are only reported when\n * their family already exists in the corpus - so `ADR-0099` in a repository\n * full of ADRs is a finding, and `T-1000` in the same repository is not.\n * - **Two candidates is worse than none.** A reference that matches several\n * documents is reported as ambiguous rather than silently bound to whichever\n * one happened to be indexed first.\n */\n\nimport type { ExtractedDocument, ReferenceCandidate } from './extract.js';\nimport {\n isDocumentTarget,\n isExternal,\n looksLikePath,\n normaliseRef,\n parseBareRef,\n parsePrefixedRef,\n splitAnchor,\n withinOneEdit,\n} from './identity.js';\nimport { basenamePosix, dirnamePosix, extnamePosix, resolveFrom } from './paths.js';\nimport type {\n DanglingRef,\n DocumentNode,\n Edge,\n ItemNode,\n MisreadKey,\n ParseProblem,\n SpecNode,\n SuppressedRef,\n} from './types.js';\n\nexport interface ResolveOptions {\n /**\n * Whether a repository-relative path exists on disk.\n *\n * Used only to tell \"you linked to a file that is not a specification\" apart\n * from \"you linked to nothing at all\", which are different mistakes with\n * different fixes.\n */\n readonly fileExists?: ((path: string) => boolean) | undefined;\n /**\n * Targets whose failure to resolve should not be reported.\n *\n * This is a *suppression* filter, not a resolution one: it is consulted only\n * when a reference has already failed to resolve. A reference that resolves\n * still becomes an edge no matter what this says, so no amount of\n * configuration can silently delete a relation from the graph.\n */\n readonly isIgnoredReference?: ((target: string) => boolean) | undefined;\n /**\n * Families that are never citations in this repository.\n *\n * `RFC 2119` is the canonical case: every specification cites it, and a\n * repository that keeps its own `RFC-*` documents will otherwise read that\n * sentence as a dangling reference to a local RFC 2119 it does not have.\n * Consulted only after resolution has failed, like every other filter here.\n */\n readonly isIgnoredFamily?: ((family: string) => boolean) | undefined;\n}\n\nexport interface ResolvedCorpus {\n readonly nodes: ReadonlyMap<string, SpecNode>;\n readonly documents: readonly DocumentNode[];\n readonly items: readonly ItemNode[];\n readonly edges: readonly Edge[];\n readonly dangling: readonly DanglingRef[];\n readonly problems: readonly ParseProblem[];\n readonly misreadKeys: readonly MisreadKey[];\n /**\n * References this repository declared none of its business.\n *\n * Not findings, and never reported as such - they are the audit trail for\n * the two settings that can silence one. See ADR-0008.\n */\n readonly suppressed: readonly SuppressedRef[];\n}\n\ninterface Index {\n readonly byId: Map<string, string>;\n readonly byAlias: Map<string, Set<string>>;\n /** The literal path of a file. Unique: no two files share one. */\n readonly byPath: Map<string, string>;\n /**\n * Spellings that address a file without naming it exactly - the extension\n * dropped, a directory standing for its README. Several files can answer to\n * one of those, so this is a set, exactly as `byAlias` is.\n */\n readonly byPathAlias: Map<string, Set<string>>;\n readonly byFamilyNumber: Map<string, Set<string>>;\n readonly families: Set<string>;\n /** Every file by the directory holding it, for a basename that was mistyped. */\n readonly byDirectory: Map<string, { stem: string; id: string }[]>;\n /**\n * Alias keys grouped by length.\n *\n * A one-edit match can only differ in length by one, so this turns the scan\n * behind a suggestion from the whole corpus into three buckets of it.\n */\n readonly aliasesByLength: Map<number, string[]>;\n readonly anchors: Map<string, ReadonlySet<string>>;\n readonly itemIds: Set<string>;\n readonly familyOf: Map<string, string | null>;\n}\n\n/** Resolves every extracted reference against the whole corpus. */\nexport function resolveCorpus(\n extracted: readonly ExtractedDocument[],\n options: ResolveOptions = {},\n): ResolvedCorpus {\n const index = buildIndex(extracted);\n const nodes = new Map<string, SpecNode>();\n const documents: DocumentNode[] = [];\n const items: ItemNode[] = [];\n const problems: ParseProblem[] = [];\n const misreadKeys: MisreadKey[] = [];\n\n for (const entry of extracted) {\n const existing = nodes.get(entry.document.id);\n if (existing && existing.kind === 'document') {\n problems.push({\n message: `duplicate document id \"${entry.document.id}\", already declared by ${existing.path}`,\n at: entry.document.at,\n });\n continue;\n }\n nodes.set(entry.document.id, entry.document);\n documents.push(entry.document);\n for (const item of entry.items) {\n // Nodes are keyed by id, so a second item would replace the first in the\n // graph while both were still counted, and one of them would vanish from\n // the export without a word.\n const taken = nodes.get(item.id);\n if (taken) {\n problems.push({\n message: `duplicate item id \"${item.id}\", already taken at ${taken.at.file}:${taken.at.span.start.line}`,\n at: item.at,\n });\n continue;\n }\n nodes.set(item.id, item);\n items.push(item);\n }\n problems.push(...entry.problems);\n misreadKeys.push(...entry.misreadKeys);\n }\n\n const edges: Edge[] = [];\n const dangling: DanglingRef[] = [];\n const suppressed: SuppressedRef[] = [];\n const byKey = new Map<string, number>();\n\n // Structural edges: a register contains the specifications written inside it.\n for (const entry of extracted) {\n if (entry.containerId === null) continue;\n if (!nodes.has(entry.containerId) || !nodes.has(entry.document.id)) continue;\n edges.push({\n kind: 'contains',\n from: entry.containerId,\n to: entry.document.id,\n origin: 'structural',\n declaredAt: entry.document.at,\n raw: entry.document.title,\n declaredIn: [entry.document.at.file],\n reflexive: false,\n });\n }\n\n // Structural edges: a document contains its items.\n for (const item of items) {\n edges.push({\n kind: 'contains',\n from: item.document,\n to: item.id,\n origin: 'structural',\n declaredAt: item.at,\n raw: item.text,\n declaredIn: [item.at.file],\n reflexive: false,\n });\n }\n\n for (const entry of extracted) {\n for (const candidate of entry.references) {\n if (!nodes.has(candidate.from)) continue;\n const outcome = resolveOne(candidate, entry, index, nodes, options);\n if (outcome === null) continue;\n if ('by' in outcome) {\n suppressed.push(outcome);\n continue;\n }\n if ('reason' in outcome) {\n dangling.push(outcome);\n continue;\n }\n // Collapse duplicates: the same relation stated twice is one edge - but\n // every declaration site is kept, because a supersession recorded in only\n // one of the two documents is itself a finding.\n const key = `${outcome.kind} ${outcome.from} ${outcome.to}`;\n const existing = byKey.get(key);\n if (existing !== undefined) {\n const previous = edges[existing] as Edge;\n if (!previous.declaredIn.includes(outcome.declaredAt.file)) {\n edges[existing] = { ...previous, declaredIn: [...previous.declaredIn, outcome.declaredAt.file] };\n }\n continue;\n }\n byKey.set(key, edges.length);\n edges.push(outcome);\n }\n }\n\n return { nodes, documents, items, edges, dangling, problems, misreadKeys, suppressed };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Indexing */\n/* -------------------------------------------------------------------------- */\n\nfunction buildIndex(extracted: readonly ExtractedDocument[]): Index {\n const index: Index = {\n byId: new Map(),\n byAlias: new Map(),\n byPath: new Map(),\n byPathAlias: new Map(),\n byFamilyNumber: new Map(),\n families: new Set(),\n byDirectory: new Map(),\n aliasesByLength: new Map(),\n anchors: new Map(),\n itemIds: new Set(),\n familyOf: new Map(),\n };\n\n for (const entry of extracted) {\n const id = entry.document.id;\n index.byId.set(normaliseRef(id), id);\n index.anchors.set(id, entry.anchors);\n index.familyOf.set(id, entry.identity.family);\n\n for (const alias of entry.document.aliases) {\n const set = index.byAlias.get(alias) ?? new Set<string>();\n set.add(id);\n index.byAlias.set(alias, set);\n }\n\n // Only a file answers to its path. A region keeps the path on its node, so a\n // finding can say where it lives and `document[path=...]` can select it, but\n // it must not be reachable *by* that path: two nodes answering to one path\n // makes every link to the file ambiguous, and this index resolves a\n // collision by keeping whichever was written last. A link to a file holding\n // a register bound to its final row, quietly and with no diagnostic, and\n // anchors were then checked against that row's span rather than the file's.\n // ADR-0009 said a region does not claim the file's path; this is the index\n // where that had to be true.\n if (entry.containerId === null) {\n const path = entry.document.path.toLowerCase();\n index.byPath.set(path, id);\n for (const spelling of pathAliases(entry.document.path)) {\n const set = index.byPathAlias.get(spelling) ?? new Set<string>();\n set.add(id);\n index.byPathAlias.set(spelling, set);\n }\n const directory = dirnamePosix(path);\n const siblings = index.byDirectory.get(directory) ?? [];\n siblings.push({ stem: stemOf(path), id });\n index.byDirectory.set(directory, siblings);\n }\n\n if (entry.identity.family !== null && entry.identity.number !== null) {\n index.families.add(entry.identity.family);\n const key = `${entry.identity.family}:${entry.identity.number}`;\n const set = index.byFamilyNumber.get(key) ?? new Set<string>();\n set.add(id);\n index.byFamilyNumber.set(key, set);\n }\n\n for (const item of entry.items) index.itemIds.add(item.id);\n }\n\n for (const alias of index.byAlias.keys()) {\n const bucket = index.aliasesByLength.get(alias.length) ?? [];\n bucket.push(alias);\n index.aliasesByLength.set(alias.length, bucket);\n }\n\n return index;\n}\n\n/** A file name with its extension taken off: `docs/a/0004-sharding.md` -> `0004-sharding`. */\nfunction stemOf(path: string): string {\n const base = basenamePosix(path);\n return base.slice(0, base.length - extnamePosix(base).length);\n}\n\n/** Every spelling of a path that addresses a file without naming it exactly. */\nfunction pathAliases(path: string): string[] {\n const keys = new Set<string>();\n const extension = extnamePosix(path);\n if (extension.length > 0) keys.add(path.slice(0, path.length - extension.length).toLowerCase());\n // `docs/adr/0007/README.md` is also addressed as `docs/adr/0007`.\n const base = basenamePosix(path);\n if (/^(readme|index)\\./i.test(base)) {\n const parent = path.slice(0, path.length - base.length - 1);\n if (parent.length > 0) keys.add(parent.toLowerCase());\n }\n // A file never addresses itself inexactly. Leaving this in would let a\n // contrived name - `docs/a.md.md`, whose stem is another file's whole path -\n // make an exact link look ambiguous.\n keys.delete(path.toLowerCase());\n return [...keys];\n}\n\n/* -------------------------------------------------------------------------- */\n/* Resolution */\n/* -------------------------------------------------------------------------- */\n\nfunction resolveOne(\n candidate: ReferenceCandidate,\n entry: ExtractedDocument,\n index: Index,\n nodes: ReadonlyMap<string, SpecNode>,\n options: ResolveOptions,\n): Edge | DanglingRef | SuppressedRef | null {\n const { target: bare, anchor } = splitAnchor(candidate.target);\n\n // A pure `#anchor` points inside the citing document.\n if (bare.length === 0 && anchor !== null) {\n return bindAnchor(candidate, entry.document.id, anchor, index, nodes, options);\n }\n\n if (isExternal(bare)) return null;\n // A link to source code, an image or a config file is not a specification\n // reference. Validating it would report an error on the most ordinary thing a\n // design document does.\n if (!isDocumentTarget(bare)) return null;\n\n const found = lookup(bare, entry, index);\n\n if (found.ids.length === 0) {\n if (candidate.opportunistic && !worthReporting(bare, index)) return null;\n const silenced = filteredBy(candidate.target, bare, options);\n if (silenced !== null) return suppression(candidate, silenced);\n // A trailing slash names a directory. Linking to one is ordinary - \"the\n // decisions live in [archive/](archive/)\" - and is not a citation of any\n // document. Resolution is still attempted first, so a directory-style\n // document written as `0007-sharding/` continues to resolve.\n if (bare.endsWith('/')) return null;\n const reason = pathMissingReason(bare, entry, options);\n return dangle(candidate, reason, found.near);\n }\n\n if (found.ids.length > 1) {\n if (candidate.opportunistic) return null;\n const silenced = filteredBy(candidate.target, bare, options);\n if (silenced !== null) return suppression(candidate, silenced);\n return dangle(candidate, 'ambiguous', found.ids);\n }\n\n const documentId = found.ids[0] as string;\n\n // A document naming itself in prose - almost always its own H1, `# ADR-0007:\n // Sharding` - is not a citation. Deliberate self-links are kept, because a\n // link that points at its own document is a real mistake worth reporting.\n if (candidate.opportunistic && documentId === entry.document.id) return null;\n\n if (anchor !== null) return bindAnchor(candidate, documentId, anchor, index, nodes, options);\n\n return makeEdge(candidate, documentId);\n}\n\ninterface Lookup {\n readonly ids: readonly string[];\n /** Near-misses worth suggesting in the report. */\n readonly near: readonly string[];\n}\n\n/**\n * The same path with its percent-escapes read.\n *\n * `[Design](docs/my%20design.md)` is what a renderer, a documentation site and\n * GitHub's own \"copy link\" all produce for a file with a space in its name, and\n * it names a real file. Returns `null` when there was nothing to decode or when\n * the escapes are malformed - `100%` in a path is not an escape sequence, and\n * `decodeURIComponent` throws on it.\n */\nfunction percentDecoded(target: string): string | null {\n if (!target.includes('%')) return null;\n try {\n const decoded = decodeURIComponent(target);\n return decoded === target ? null : decoded;\n } catch {\n return null;\n }\n}\n\nfunction lookup(target: string, entry: ExtractedDocument, index: Index): Lookup {\n const exact = lookupExact(target, entry, index);\n if (exact.length > 0) return { ids: exact, near: [] };\n // Tried second and never first, so a repository holding a file whose name\n // genuinely contains a percent escape keeps resolving by its written spelling.\n const decoded = percentDecoded(target);\n const relaxed = decoded === null ? [] : lookupExact(decoded, entry, index);\n if (relaxed.length > 0) return { ids: relaxed, near: [] };\n // Suggestions are computed only once resolution has failed outright, so their\n // cost is bounded by the number of findings rather than by the corpus.\n return { ids: [], near: nearMisses(target, entry, index) };\n}\n\nfunction lookupExact(target: string, entry: ExtractedDocument, index: Index): readonly string[] {\n if (looksLikePath(target)) {\n const resolved = resolveFrom(entry.document.path, target).toLowerCase();\n // Naming the file exactly is never ambiguous, whatever else is spelled the\n // same way.\n const byPath = index.byPath.get(resolved);\n if (byPath) return [byPath];\n // An inexact spelling can belong to more than one file: `docs/A` is both\n // `docs/A.md` with its extension dropped and `docs/A/README.md` standing\n // for its directory. Handing back every claimant makes that an\n // ambiguous-reference the author can settle, rather than a silent pick of\n // whichever happened to be indexed last.\n const spelled = index.byPathAlias.get(resolved);\n if (spelled && spelled.size > 0) return [...spelled];\n // A path may still be spelled as an identifier in a nested folder layout.\n const stem = basenamePosix(resolved);\n const byStem = index.byAlias.get(normaliseRef(stem.replace(/\\.[^.]+$/, '')));\n if (byStem && byStem.size > 0) return [...byStem];\n return [];\n }\n\n const key = normaliseRef(target);\n if (key.length === 0) return [];\n\n const byId = index.byId.get(key);\n if (byId) return [byId];\n\n const byAlias = index.byAlias.get(key);\n if (byAlias && byAlias.size > 0) return [...byAlias];\n\n const prefixed = parsePrefixedRef(target);\n if (prefixed) {\n const byFamily = index.byFamilyNumber.get(`${prefixed.family}:${prefixed.number}`);\n if (byFamily && byFamily.size > 0) return [...byFamily];\n return [];\n }\n\n // A bare number resolves only inside the citing document's own family. A\n // repository with both `adr/0007` and `rfc/0007` is ordinary, and guessing\n // between them would be worse than reporting nothing.\n const number = parseBareRef(target);\n if (number !== null) {\n const family = index.familyOf.get(entry.document.id) ?? null;\n if (family === null) return [];\n const byFamily = index.byFamilyNumber.get(`${family}:${number}`);\n if (byFamily && byFamily.size > 0) return [...byFamily];\n }\n\n return [];\n}\n\n/* -------------------------------------------------------------------------- */\n/* Near misses */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The one document a failed reference was probably meant to name.\n *\n * A suggestion is cheap to read and expensive to get wrong: \"did you mean\n * ADR-0008?\" against a citation that meant ADR-0012 sends a reader to the wrong\n * decision with a confidence nobody earned. So the bar is not closeness, it is\n * closeness *in the part of the spelling that is not the identity*. A family\n * name is a word people misremember. A number is the identity itself, and\n * `ADR-0009` sits one edit from every neighbour it has - so numbers are never\n * guessed at, and a repository of fifteen ADRs citing a sixteenth is told the\n * plain truth instead.\n *\n * Two gates, plus a fallback:\n *\n * - a path in the right directory whose basename is one edit out - a typo;\n * - a family one edit out with its number intact - `ARD-0009` for `ADR-0009`.\n *\n * Anything else falls through to a one-edit match against the folded spellings\n * documents already answer to, which is where a mistyped slug or wiki name\n * lands.\n *\n * There is deliberately no gate for a file that moved. Resolution already binds\n * a path by its basename, so `../guides/onboarding.md` finds the document that\n * is now in `handbook/` without anybody being asked to confirm a guess - and a\n * suggestion nobody needs is a suggestion that can only be wrong.\n *\n * Every gate ends the same way: **exactly one** candidate, or nothing. Two\n * suggestions is the ambiguity this module refuses to resolve anywhere else,\n * and the tail of a hint is no place to start.\n */\nfunction nearMisses(target: string, entry: ExtractedDocument, index: Index): string[] {\n if (looksLikePath(target)) {\n const resolved = resolveFrom(entry.document.path, target).toLowerCase();\n const stem = stemOf(resolved);\n const siblings = index.byDirectory.get(dirnamePosix(resolved)) ?? [];\n return sole(siblings.filter((file) => withinOneEdit(file.stem, stem)).map((file) => file.id));\n }\n\n const prefixed = parsePrefixedRef(target);\n if (prefixed !== null) {\n const hits: string[] = [];\n for (const family of index.families) {\n // The family as written needs no exclusion: one edit is never zero edits.\n if (!withinOneEdit(family.toLowerCase(), prefixed.family.toLowerCase())) continue;\n for (const id of index.byFamilyNumber.get(`${family}:${prefixed.number}`) ?? []) hits.push(id);\n }\n return sole(hits);\n }\n\n // A bare `12` carries nothing but a number, which is the one thing this\n // refuses to guess at.\n if (parseBareRef(target) !== null) return [];\n\n const key = normaliseRef(target);\n if (key.length < MIN_SUGGESTIBLE) return [];\n const hits: string[] = [];\n for (const length of [key.length - 1, key.length, key.length + 1]) {\n for (const alias of index.aliasesByLength.get(length) ?? []) {\n if (!withinOneEdit(alias, key)) continue;\n for (const id of index.byAlias.get(alias) ?? []) hits.push(id);\n }\n }\n return sole(hits);\n}\n\n/**\n * How long a folded spelling has to be before one edit means anything.\n *\n * Below six characters an edit is most of the word, and every corpus is full of\n * short names that differ by exactly that much.\n */\nconst MIN_SUGGESTIBLE = 6;\n\n/** The candidates, if there is exactly one of them. Otherwise nothing. */\nfunction sole(ids: Iterable<string>): string[] {\n const unique = new Set(ids);\n return unique.size === 1 ? [...unique] : [];\n}\n\n/**\n * Which setting, if any, declared this reference none of the repository's\n * business.\n *\n * Returns the mechanism rather than a boolean so the audit trail can say which\n * line of configuration to go and look at. A team that silenced eight things\n * with one glob and one with a family needs to be told them apart.\n */\nfunction filteredBy(target: string, bare: string, options: ResolveOptions): SuppressedRef['by'] | null {\n if (options.isIgnoredReference?.(target)) return 'reference';\n const prefixed = parsePrefixedRef(bare);\n if (prefixed !== null && options.isIgnoredFamily?.(prefixed.family) === true) return 'family';\n return null;\n}\n\n/**\n * Whether an unresolved bare identifier deserves a report.\n *\n * Only when the corpus already contains that family. `ADR-0099` in a repository\n * of ADRs is a real dangling citation; `T-1000` in the same repository is a\n * sentence about a robot.\n */\nfunction worthReporting(target: string, index: Index): boolean {\n const prefixed = parsePrefixedRef(target);\n return prefixed !== null && index.families.has(prefixed.family);\n}\n\nfunction pathMissingReason(\n target: string,\n entry: ExtractedDocument,\n options: ResolveOptions,\n): DanglingRef['reason'] {\n if (!looksLikePath(target) || !options.fileExists) return 'unknown-target';\n const resolved = resolveFrom(entry.document.path, target);\n return options.fileExists(resolved) ? 'not-a-spec' : 'unknown-target';\n}\n\n/**\n * Binds a `#anchor` to an item or a section.\n *\n * Anchors are how a delegation names a specific obligation rather than a whole\n * document, so resolving them precisely is what lets a ghost-handover finding\n * say *which* question was handed into the archive.\n */\nfunction bindAnchor(\n candidate: ReferenceCandidate,\n documentId: string,\n anchor: string,\n index: Index,\n nodes: ReadonlyMap<string, SpecNode>,\n options: ResolveOptions,\n): Edge | DanglingRef | SuppressedRef | null {\n const itemId = `${documentId}#${anchor}`;\n if (index.itemIds.has(itemId)) return makeEdge(candidate, itemId);\n\n const anchors = index.anchors.get(documentId);\n if (anchors?.has(anchor.toLowerCase())) return makeEdge(candidate, documentId);\n\n // Some renderers slugify differently; try the loosest reasonable match before\n // calling it broken.\n const loose = anchor.toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, '-').replace(/^-|-$/g, '');\n if (anchors?.has(loose)) return makeEdge(candidate, documentId);\n\n const silenced = filteredBy(candidate.target, splitAnchor(candidate.target).target, options);\n if (silenced !== null) return suppression(candidate, silenced);\n\n const candidates = [...(nodes.keys() as Iterable<string>)].filter(\n (id) => id.startsWith(`${documentId}#`) && id.toLowerCase().includes(loose),\n );\n return {\n kind: candidate.kind,\n from: candidate.from,\n target: candidate.target,\n reason: 'unknown-anchor',\n origin: candidate.origin,\n declaredAt: candidate.declaredAt,\n raw: candidate.raw,\n candidates,\n };\n}\n\nfunction makeEdge(candidate: ReferenceCandidate, resolved: string): Edge {\n const from = candidate.inverted ? resolved : candidate.from;\n const to = candidate.inverted ? candidate.from : resolved;\n return {\n kind: candidate.kind,\n from,\n to,\n origin: candidate.origin,\n declaredAt: candidate.declaredAt,\n raw: candidate.raw,\n declaredIn: [candidate.declaredAt.file],\n reflexive: documentOf(from) === documentOf(to),\n };\n}\n\nfunction suppression(candidate: ReferenceCandidate, by: SuppressedRef['by']): SuppressedRef {\n return { target: candidate.target, from: candidate.from, at: candidate.declaredAt, by };\n}\n\nfunction dangle(\n candidate: ReferenceCandidate,\n reason: DanglingRef['reason'],\n candidates: readonly string[],\n): DanglingRef {\n return {\n kind: candidate.kind,\n from: candidate.from,\n target: candidate.target,\n reason,\n origin: candidate.origin,\n declaredAt: candidate.declaredAt,\n raw: candidate.raw,\n candidates,\n };\n}\n\n/** The document part of a node id: `ADR-7#q.1` -> `ADR-7`. */\nexport function documentOf(nodeId: string): string {\n const hash = nodeId.indexOf('#');\n return hash === -1 ? nodeId : nodeId.slice(0, hash);\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -199,6 +199,14 @@ export interface DocumentNode extends NodeBase {
199
199
  }
200
200
  export interface ItemNode extends NodeBase {
201
201
  readonly kind: 'item';
202
+ /**
203
+ * Whether the id was written by an author rather than numbered by position.
204
+ *
205
+ * A numbered id is the item's ordinal within its section, so inserting one
206
+ * item renumbers every item after it. Only a declared id names the same item
207
+ * in two states of a repository (ADR-0020).
208
+ */
209
+ readonly declared: boolean;
202
210
  /** Owning document id. */
203
211
  readonly document: string;
204
212
  /** Heading path the item sits under, outermost first. */