@descent-vtt/spec-graph 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +410 -0
  2. package/README.md +102 -17
  3. package/dist/cli.d.ts +2 -2
  4. package/dist/cli.js +38 -19
  5. package/dist/cli.js.map +1 -1
  6. package/dist/directives.d.ts +9 -2
  7. package/dist/directives.js +15 -4
  8. package/dist/directives.js.map +1 -1
  9. package/dist/extract.d.ts +1 -1
  10. package/dist/extract.js +50 -16
  11. package/dist/extract.js.map +1 -1
  12. package/dist/glob.d.ts +44 -44
  13. package/dist/glob.js +152 -116
  14. package/dist/glob.js.map +1 -1
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +4 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/lifecycle.js +10 -2
  19. package/dist/lifecycle.js.map +1 -1
  20. package/dist/markdown.d.ts +53 -161
  21. package/dist/markdown.js +42 -864
  22. package/dist/markdown.js.map +1 -1
  23. package/dist/report.d.ts +23 -0
  24. package/dist/report.js +80 -0
  25. package/dist/report.js.map +1 -1
  26. package/dist/rules.js +48 -14
  27. package/dist/rules.js.map +1 -1
  28. package/dist/sections.d.ts +1 -1
  29. package/dist/sections.js +7 -3
  30. package/dist/sections.js.map +1 -1
  31. package/dist/select.d.ts +2 -2
  32. package/dist/select.js +3 -3
  33. package/dist/select.js.map +1 -1
  34. package/dist/source.d.ts +6 -19
  35. package/dist/source.js +4 -70
  36. package/dist/source.js.map +1 -1
  37. package/dist/types.d.ts +23 -3
  38. package/dist/types.js +1 -1
  39. package/dist/types.js.map +1 -1
  40. package/dist/vendor/spec-core/markdown/frontmatter.d.ts +103 -0
  41. package/dist/vendor/spec-core/markdown/frontmatter.js +459 -0
  42. package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -0
  43. package/dist/vendor/spec-core/markdown/headings.d.ts +45 -0
  44. package/dist/vendor/spec-core/markdown/headings.js +199 -0
  45. package/dist/vendor/spec-core/markdown/headings.js.map +1 -0
  46. package/dist/vendor/spec-core/markdown/index.d.ts +5 -0
  47. package/dist/vendor/spec-core/markdown/index.js +4 -0
  48. package/dist/vendor/spec-core/markdown/index.js.map +1 -0
  49. package/dist/vendor/spec-core/markdown/layout.d.ts +39 -0
  50. package/dist/vendor/spec-core/markdown/layout.js +28 -0
  51. package/dist/vendor/spec-core/markdown/layout.js.map +1 -0
  52. package/dist/vendor/spec-core/markdown/links.d.ts +22 -0
  53. package/dist/vendor/spec-core/markdown/links.js +364 -0
  54. package/dist/vendor/spec-core/markdown/links.js.map +1 -0
  55. package/dist/vendor/spec-core/markdown/lists.d.ts +22 -0
  56. package/dist/vendor/spec-core/markdown/lists.js +127 -0
  57. package/dist/vendor/spec-core/markdown/lists.js.map +1 -0
  58. package/dist/vendor/spec-core/markdown/scan.d.ts +36 -0
  59. package/dist/vendor/spec-core/markdown/scan.js +439 -0
  60. package/dist/vendor/spec-core/markdown/scan.js.map +1 -0
  61. package/dist/vendor/spec-core/markdown/syntax.d.ts +75 -0
  62. package/dist/vendor/spec-core/markdown/syntax.js +181 -0
  63. package/dist/vendor/spec-core/markdown/syntax.js.map +1 -0
  64. package/dist/vendor/spec-core/markdown/tables.d.ts +18 -0
  65. package/dist/vendor/spec-core/markdown/tables.js +86 -0
  66. package/dist/vendor/spec-core/markdown/tables.js.map +1 -0
  67. package/dist/vendor/spec-core/markdown/types.d.ts +287 -0
  68. package/dist/vendor/spec-core/markdown/types.js +9 -0
  69. package/dist/vendor/spec-core/markdown/types.js.map +1 -0
  70. package/dist/vendor/spec-core/path/index.d.ts +1 -0
  71. package/dist/vendor/spec-core/path/index.js +2 -0
  72. package/dist/vendor/spec-core/path/index.js.map +1 -0
  73. package/dist/vendor/spec-core/path/posix.d.ts +83 -0
  74. package/dist/vendor/spec-core/path/posix.js +150 -0
  75. package/dist/vendor/spec-core/path/posix.js.map +1 -0
  76. package/dist/vendor/spec-core/pattern/automaton.d.ts +129 -0
  77. package/dist/vendor/spec-core/pattern/automaton.js +340 -0
  78. package/dist/vendor/spec-core/pattern/automaton.js.map +1 -0
  79. package/dist/vendor/spec-core/pattern/charset.d.ts +58 -0
  80. package/dist/vendor/spec-core/pattern/charset.js +116 -0
  81. package/dist/vendor/spec-core/pattern/charset.js.map +1 -0
  82. package/dist/vendor/spec-core/pattern/glob.d.ts +121 -0
  83. package/dist/vendor/spec-core/pattern/glob.js +481 -0
  84. package/dist/vendor/spec-core/pattern/glob.js.map +1 -0
  85. package/dist/vendor/spec-core/pattern/index.d.ts +6 -0
  86. package/dist/vendor/spec-core/pattern/index.js +4 -0
  87. package/dist/vendor/spec-core/pattern/index.js.map +1 -0
  88. package/dist/{regex.d.ts → vendor/spec-core/pattern/regex.d.ts} +20 -29
  89. package/dist/{regex.js → vendor/spec-core/pattern/regex.js} +40 -49
  90. package/dist/vendor/spec-core/pattern/regex.js.map +1 -0
  91. package/dist/vendor/spec-core/text/index.d.ts +2 -0
  92. package/dist/vendor/spec-core/text/index.js +2 -0
  93. package/dist/vendor/spec-core/text/index.js.map +1 -0
  94. package/dist/vendor/spec-core/text/lines.d.ts +72 -0
  95. package/dist/vendor/spec-core/text/lines.js +156 -0
  96. package/dist/vendor/spec-core/text/lines.js.map +1 -0
  97. package/dist/yaml.d.ts +44 -12
  98. package/dist/yaml.js +115 -206
  99. package/dist/yaml.js.map +1 -1
  100. package/package.json +3 -2
  101. package/src/vendor/spec-core/LICENSE +21 -0
  102. package/src/vendor/spec-core/README.md +8 -0
  103. package/dist/regex.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"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"]}
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 { createHash } from 'node:crypto';\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 const unread = options.verbose ? 0 : unreadFrontMatter(result);\n if (unread > 0) {\n lines.push(`${paint.warn(marks.warn)} ${unreadNotice(unread)}`, '');\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 * How many front-matter values the graph is built from went unread.\n *\n * Parse problems are listed only under `--verbose`, and most of them can wait\n * there. These cannot: `status: Superseded by ADR-3: see notes` is not read,\n * the document reads as unknown, and a failing check reports that the graph is\n * consistent. So a default run says how many there are, and where to look.\n */\nfunction unreadFrontMatter(result: AnalysisResult): number {\n return result.problems.filter((problem) => problem.unread === true).length;\n}\n\nfunction unreadNotice(count: number): string {\n return `${count} front-matter ${plural(count, 'value')} not read - see --verbose`;\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 const unread = options.verbose ? 0 : unreadFrontMatter(result);\n if (unread > 0) lines.push(`${unreadNotice(unread)}.`, '');\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\n/* -------------------------------------------------------------------------- */\n/* GitLab Code Quality */\n/* -------------------------------------------------------------------------- */\n\ntype GitlabSeverity = 'critical' | 'major' | 'minor' | 'info';\n\n/**\n * GitLab's Code Quality report, which a merge request reads to show the\n * findings a change introduced and the ones it resolved - what SARIF is to\n * GitHub, so the family is not GitHub's alone.\n *\n * The format is GitLab's and carries no version of its own: a JSON array with\n * the five fields GitLab reads and nothing else.\n *\n * `fingerprint` is how GitLab matches a finding in the merge request to the\n * same finding on the target branch, so it holds what the finding is about and\n * nothing that moves when something else changes: the rule, the specification\n * and what within it, hashed - the identity a baseline counts by. Not the line,\n * so a paragraph moved above a finding does not make it new. Not the message,\n * which carries counts: ticking one of three boxes turned \"holds 3 open\n * obligations\" into \"holds 2\", and GitLab showed one finding resolved and one\n * introduced. Two findings that agree on all three - one broken link written\n * twice in a document - are told apart by their order, the second hashed with a\n * `2`: GitLab tells issues apart by fingerprint, and two that shared one would\n * be read as one.\n */\nexport function formatGitlab(\n result: AnalysisResult,\n options: { escalated?: ReadonlySet<AnyRuleId> | undefined } = {},\n): string {\n const escalated = options.escalated ?? EMPTY_RULES;\n const occurrences = new Map<string, number>();\n const issues = result.diagnostics.map((diagnostic) => {\n const { document, subject } = fingerprintOf(result.graph, diagnostic);\n const identity = [diagnostic.rule, document, subject];\n const key = JSON.stringify(identity);\n const occurrence = (occurrences.get(key) ?? 0) + 1;\n occurrences.set(key, occurrence);\n return {\n description: `${diagnostic.message}. ${diagnostic.hint}`,\n check_name: diagnostic.rule,\n fingerprint: createHash('sha256')\n .update(occurrence === 1 ? key : JSON.stringify([...identity, occurrence]))\n .digest('hex'),\n severity: gitlabSeverity(diagnostic.severity, escalated.has(diagnostic.rule)),\n location: { path: diagnostic.at.file, lines: { begin: diagnostic.at.span.start.line } },\n };\n });\n return `${JSON.stringify(issues, null, 2)}\\n`;\n}\n\n/**\n * spec-graph's three severities on GitLab's five. An error is critical: it\n * fails the build. One that is only an error because `--strict` raised it is\n * major, which is the one place the report can say so. A warning is minor,\n * and a note is information. `blocker` is left to tools that know more about\n * what cannot ship than a documentation linter does.\n */\nfunction gitlabSeverity(severity: Severity, escalated: boolean): GitlabSeverity {\n switch (severity) {\n case 'error':\n return escalated ? 'major' : 'critical';\n case 'warn':\n return 'minor';\n default:\n return 'info';\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/rules.js CHANGED
@@ -52,7 +52,7 @@ export const RULE_DESCRIPTIONS = Object.freeze({
52
52
  'circular-delegation': 'obligations or supersessions form a cycle, so none of them can ever land',
53
53
  'orphaned-obligation': 'a retired or frozen document still holds open obligations',
54
54
  'live-supersession': 'a document has been superseded but still presents itself as current',
55
- 'unreciprocated-supersession': 'a retired document does not say what replaced it',
55
+ 'unreciprocated-supersession': 'a retired or archived document does not say what replaced it',
56
56
  'state-conflict': 'an item declares two states that disagree about whether work remains',
57
57
  'self-reference': 'a document delegates to or depends on itself',
58
58
  'unknown-relation-key': 'a front-matter key reads as a relation but declares none',
@@ -193,6 +193,13 @@ const REFERENCE_RULES = new Set([
193
193
  * Stated once, here, rather than as a guard repeated in eight rules: the
194
194
  * exemption is a property of what counts as a finding, not of any one rule, and
195
195
  * a rule added later inherits it without having to remember. See ADR-0011.
196
+ *
197
+ * All of that is a log's, declared by `historyPatterns` or `@spec-history`. A
198
+ * document that is a record because it says `archived` is a closed round of
199
+ * work, and nothing about it makes its claims history: a supersession it
200
+ * declares, a cycle it closes and a link to itself are still somebody's to
201
+ * correct. What it owes and what it rests on are history, as they were when
202
+ * `archived` read as retired, and that is all it is exempt from.
196
203
  */
197
204
  function exempt(graph, rule, nodes) {
198
205
  if (REFERENCE_RULES.has(rule))
@@ -200,8 +207,17 @@ function exempt(graph, rule, nodes) {
200
207
  const subject = nodes[0];
201
208
  if (subject === undefined)
202
209
  return false;
203
- return graph.owningDocument(subject)?.phase === 'record';
210
+ const owner = graph.owningDocument(subject);
211
+ if (owner?.phase !== 'record')
212
+ return false;
213
+ return owner.history || CLOSED_ROUND_RULES.has(rule);
204
214
  }
215
+ /**
216
+ * The rules an archived document is exempt from as their subject: work it
217
+ * hands on and premises it rests on. Their queries left a retired source out,
218
+ * and `archived` was retired until it became a record.
219
+ */
220
+ const CLOSED_ROUND_RULES = new Set(['ghost-handover', 'stale-premise']);
205
221
  /* -------------------------------------------------------------------------- */
206
222
  /* Ghost handovers */
207
223
  /* -------------------------------------------------------------------------- */
@@ -223,7 +239,8 @@ function ghostHandovers(graph, emit) {
223
239
  const targetDocument = graph.owningDocument(target.id);
224
240
  if (!targetDocument)
225
241
  continue;
226
- const sealed = SEALED_WORD[targetDocument.phase] ?? 'frozen';
242
+ const seal = sealOf(targetDocument);
243
+ const sealed = SEALED_WORD[seal] ?? 'frozen';
227
244
  const what = source.kind === 'item' ? 'open obligation' : 'obligation';
228
245
  const verb = EDGE_TRAITS[edge.kind].phrase;
229
246
  claimed.add(edgeKey(edge));
@@ -235,21 +252,27 @@ function ghostHandovers(graph, emit) {
235
252
  related(targetDocument.statusAt ?? targetDocument.at, `${targetDocument.id} is ${sealed}${statusSuffix(targetDocument)}`),
236
253
  ...(source.kind === 'item' ? [related(source.at, `the obligation: ${source.text}`)] : []),
237
254
  ],
238
- hint: HANDOVER_HINT[targetDocument.phase]?.(targetDocument.id) ?? FROZEN_HINT(targetDocument.id),
255
+ hint: HANDOVER_HINT[seal]?.(targetDocument.id) ?? FROZEN_HINT(targetDocument.id),
239
256
  }));
240
257
  }
241
258
  return claimed;
242
259
  }
260
+ /** Which kind of sealed document this is: its phase, or `archived` for a closed round. */
261
+ function sealOf(document) {
262
+ return document.phase === 'record' && !document.history ? 'archived' : document.phase;
263
+ }
243
264
  /** How a sealed target is described in a ghost-handover message. */
244
265
  const SEALED_WORD = {
245
266
  retired: 'retired',
246
267
  record: 'a historical record',
268
+ archived: 'archived',
247
269
  };
248
270
  const FROZEN_HINT = (id) => `${id} is frozen and cannot take on new work - open an amendment, or close this here`;
249
271
  /** What to do about work handed into each kind of sealed document. */
250
272
  const HANDOVER_HINT = {
251
273
  retired: (id) => `nothing will be read from ${id} again - re-home this in a live document, or close it here`,
252
274
  record: (id) => `${id} is a log of what happened and will never act - re-home this in a live document`,
275
+ archived: (id) => `${id} is a closed round of work and will never act - re-home this in a live document`,
253
276
  };
254
277
  /** Identity of a relation, for the hand-off between overlapping rules. */
255
278
  function edgeKey(edge) {
@@ -425,9 +448,10 @@ function circularDelegations(graph, emit) {
425
448
  if (members.length < 2)
426
449
  continue;
427
450
  // A cycle is a set, not a subject, so the exemption at `emit` cannot see it.
428
- // One record in the loop means the loop is partly a report of what was once
429
- // said, and nothing in it is owed by anybody.
430
- if (members.some((member) => member.phase === 'record'))
451
+ // One log in the loop means the loop is partly a report of what was once
452
+ // said, and nothing in it is owed by anybody. An archived document in it
453
+ // is not a log: its half of the loop is a claim it still makes.
454
+ if (members.some((member) => member.history))
431
455
  continue;
432
456
  const edges = cycleEdges(graph, component, kinds);
433
457
  const onlySupersession = edges.length > 0 && edges.every((edge) => edge.kind === 'supersedes');
@@ -504,14 +528,19 @@ function supersessions(graph, emit) {
504
528
  const superseding = graph.document(edge.from);
505
529
  if (!superseded || !superseding)
506
530
  continue;
507
- // A record narrating "ADR-0005 replaced ADR-0001" is reporting a
531
+ // A log narrating "ADR-0005 replaced ADR-0001" is reporting a
508
532
  // supersession, not declaring one. Both hints below ask somebody to edit
509
533
  // the document that made the claim, and a log is the one document nobody
510
534
  // can edit - it says what was true when it was written. The exemption at
511
- // `emit` cannot see this: the subject here is the *other* document.
512
- if (superseding.phase === 'record')
535
+ // `emit` cannot see this: the subject here is the *other* document. An
536
+ // archived brief that says it supersedes another is declaring it.
537
+ if (superseding.history)
513
538
  continue;
514
- if (superseded.phase !== 'retired' && superseded.phase !== 'unknown') {
539
+ // Closed either way: an archived document is not live, and like a retired
540
+ // one it can fail to say what replaced it. A log in its place is the
541
+ // subject, and exempt at `emit`.
542
+ const archived = superseded.phase === 'record';
543
+ if (superseded.phase !== 'retired' && !archived && superseded.phase !== 'unknown') {
515
544
  emit('live-supersession', () => ({
516
545
  // The fix belongs in the superseded document, so that is where the
517
546
  // finding points - not at the document that made the claim.
@@ -523,13 +552,18 @@ function supersessions(graph, emit) {
523
552
  }));
524
553
  continue;
525
554
  }
526
- if (superseded.phase === 'retired' && !edge.declaredIn.includes(superseded.path)) {
555
+ if ((superseded.phase === 'retired' || archived) && !edge.declaredIn.includes(superseded.path)) {
527
556
  emit('unreciprocated-supersession', () => ({
528
- message: `${superseded.id} is retired but never says that ${superseding.id} replaced it`,
557
+ message: `${superseded.id} is ${archived ? 'archived' : 'retired'} but never says that ${superseding.id} replaced it`,
529
558
  at: superseded.statusAt ?? superseded.at,
530
559
  nodes: [superseded.id, superseding.id],
531
560
  related: [related(edge.declaredAt, `only ${superseding.id} records the relationship`)],
532
- hint: `add "superseded-by: ${superseding.id}" to ${superseded.path} so a reader who lands there is redirected`,
561
+ // Archived and superseded is retired, so that status also tells what
562
+ // rests on the document that it no longer holds, which a
563
+ // `superseded-by` key beside `archived` would not.
564
+ hint: archived
565
+ ? `make the status of ${superseded.path} "archived, superseded by ${superseding.id}" so a reader who lands there is redirected`
566
+ : `add "superseded-by: ${superseding.id}" to ${superseded.path} so a reader who lands there is redirected`,
533
567
  }));
534
568
  }
535
569
  }