@descent-vtt/spec-graph 0.14.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +8 -6
- package/dist/report.d.ts +5 -1
- package/dist/report.js +15 -6
- package/dist/report.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,22 @@ the family's
|
|
|
11
11
|
[versioning policy](https://github.com/DescentVTT/spec-core/blob/main/docs/adr/0009-versions-before-1-0.md)
|
|
12
12
|
records.
|
|
13
13
|
|
|
14
|
+
## 0.14.1
|
|
15
|
+
|
|
16
|
+
`FORCE_COLOR=false` forced colour on, and a Windows console with
|
|
17
|
+
`WT_SESSION` or `TERM_PROGRAM` set to nothing was sent the Unicode glyphs;
|
|
18
|
+
each is read now as the rest of the family reads it.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- `FORCE_COLOR=false` turns colour off, as `FORCE_COLOR=0` does and as Node
|
|
23
|
+
reads it; it forced colour on, into a pipe too. Any other value that is not
|
|
24
|
+
empty still forces colour on, `true`, `1` and `FALSE` among them.
|
|
25
|
+
- On Windows, `WT_SESSION` or `TERM_PROGRAM` set to nothing is read as unset,
|
|
26
|
+
as `NO_COLOR` and `FORCE_COLOR` are: a console with `WT_SESSION=` was taken
|
|
27
|
+
for Windows Terminal and sent the Unicode glyphs, and gets the ASCII ones
|
|
28
|
+
now unless the other variable names a terminal.
|
|
29
|
+
|
|
14
30
|
## 0.14.0
|
|
15
31
|
|
|
16
32
|
An input that is set and names nothing - a family name no family has, a list
|
package/README.md
CHANGED
|
@@ -1150,14 +1150,16 @@ npx --no-install @descent-vtt/spec-graph --format json | jq -r '.summary'
|
|
|
1150
1150
|
### Colour and glyphs
|
|
1151
1151
|
|
|
1152
1152
|
`--color` and `--no-color` decide, then the environment, in this order:
|
|
1153
|
-
`NO_COLOR` set and not empty turns colour off; `FORCE_COLOR` set
|
|
1154
|
-
|
|
1153
|
+
`NO_COLOR` set and not empty turns colour off; `FORCE_COLOR` set to exactly
|
|
1154
|
+
`0` or exactly `false` turns it off, on a terminal too, and set to anything
|
|
1155
|
+
else that is not empty turns it on; a `TERM` of `dumb` turns it off; otherwise
|
|
1155
1156
|
the report is coloured when stdout is a terminal. `CI` is not read.
|
|
1156
1157
|
|
|
1157
1158
|
`--ascii` draws the report in ASCII glyphs, and so does `SPEC_GRAPH_ASCII`
|
|
1158
1159
|
set to anything but `0`, `false` or nothing. Without either, a Windows console
|
|
1159
|
-
that sets neither `WT_SESSION` nor `TERM_PROGRAM
|
|
1160
|
-
terminal the
|
|
1160
|
+
that sets neither `WT_SESSION` nor `TERM_PROGRAM`, or sets them to nothing,
|
|
1161
|
+
gets ASCII and every other terminal the Unicode glyphs, `✖`, `⚠`, `↳` and
|
|
1162
|
+
the like.
|
|
1161
1163
|
|
|
1162
1164
|
## In CI
|
|
1163
1165
|
|
|
@@ -1418,9 +1420,9 @@ tools share, whose code is copied into `src/vendor/` and checked by hash rather
|
|
|
1418
1420
|
than installed. So the whole package is auditable in an afternoon — and nothing
|
|
1419
1421
|
in the pipeline can take longer than its input.
|
|
1420
1422
|
|
|
1421
|
-
**Verified, not just covered.** 2,
|
|
1423
|
+
**Verified, not just covered.** 2,148 tests; 99.4% statement and 99.8% line
|
|
1422
1424
|
coverage. Coverage says a line ran, so the suite is also held to a mutation
|
|
1423
|
-
score - 96.50% over 8,
|
|
1425
|
+
score - 96.50% over 8,841 mutants, measured by CI's full sweep, and a build
|
|
1424
1426
|
fails under 93 - because a vocabulary entry or a boundary
|
|
1425
1427
|
condition can be weakened by an ordinary-looking refactor without a single test
|
|
1426
1428
|
going red. [ADR-0007](https://github.com/DescentVTT/spec-graph/blob/main/docs/adr/0007-mutation-testing.md) is straight about what
|
package/dist/report.d.ts
CHANGED
|
@@ -70,7 +70,11 @@ export interface ColorEnvironment {
|
|
|
70
70
|
readonly platform?: NodeJS.Platform | undefined;
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
|
-
* Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to
|
|
73
|
+
* Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to
|
|
74
|
+
* TTY, as the family reads them (spec-core's ADR-0005): `NO_COLOR` set to
|
|
75
|
+
* anything first; then `FORCE_COLOR`, off for exactly `0` or exactly `false`
|
|
76
|
+
* and on for anything else; then `TERM=dumb`. Either of the first two set to
|
|
77
|
+
* nothing is as unset.
|
|
74
78
|
*
|
|
75
79
|
* `CI` is not read. It says who started the run and nothing of what the
|
|
76
80
|
* stream draws: a pipeline's log that is a terminal draws colour, spec-brief
|
package/dist/report.js
CHANGED
|
@@ -16,7 +16,11 @@ import { formatRef } from './source.js';
|
|
|
16
16
|
import { DEFAULT_SEVERITIES, RULE_DESCRIPTIONS, RULE_IDS } from './rules.js';
|
|
17
17
|
import { displayWidth } from './vendor/spec-core/text/index.js';
|
|
18
18
|
/**
|
|
19
|
-
* Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to
|
|
19
|
+
* Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to
|
|
20
|
+
* TTY, as the family reads them (spec-core's ADR-0005): `NO_COLOR` set to
|
|
21
|
+
* anything first; then `FORCE_COLOR`, off for exactly `0` or exactly `false`
|
|
22
|
+
* and on for anything else; then `TERM=dumb`. Either of the first two set to
|
|
23
|
+
* nothing is as unset.
|
|
20
24
|
*
|
|
21
25
|
* `CI` is not read. It says who started the run and nothing of what the
|
|
22
26
|
* stream draws: a pipeline's log that is a terminal draws colour, spec-brief
|
|
@@ -26,11 +30,14 @@ export function shouldUseColor(environment = {}) {
|
|
|
26
30
|
const env = environment.env ?? process.env;
|
|
27
31
|
if (env['NO_COLOR'] !== undefined && env['NO_COLOR'] !== '')
|
|
28
32
|
return false;
|
|
29
|
-
// `
|
|
30
|
-
//
|
|
31
|
-
|
|
33
|
+
// `0` and `false` are how the convention writes off, as Node and
|
|
34
|
+
// supports-color read them, so each has to win over an attached TTY rather
|
|
35
|
+
// than merely fail to force colour on: `false` used to force it. The two
|
|
36
|
+
// spellings exactly; every other value that is not empty forces colour on.
|
|
37
|
+
const forced = env['FORCE_COLOR'];
|
|
38
|
+
if (forced === '0' || forced === 'false')
|
|
32
39
|
return false;
|
|
33
|
-
if (
|
|
40
|
+
if (forced !== undefined && forced !== '')
|
|
34
41
|
return true;
|
|
35
42
|
if (env['TERM'] === 'dumb')
|
|
36
43
|
return false;
|
|
@@ -51,7 +58,9 @@ export function shouldUseAscii(environment = {}) {
|
|
|
51
58
|
if ((environment.platform ?? process.platform) !== 'win32')
|
|
52
59
|
return false;
|
|
53
60
|
// Windows Terminal and modern shells set these; the legacy console does not.
|
|
54
|
-
|
|
61
|
+
// Set to nothing is as unset, as for every convention's variable: `WT_SESSION=`
|
|
62
|
+
// is a script clearing it, and used to read as a terminal announcing itself.
|
|
63
|
+
return (env['WT_SESSION'] ?? '') === '' && (env['TERM_PROGRAM'] ?? '') === '';
|
|
55
64
|
}
|
|
56
65
|
const EMPTY_RULES = new Set();
|
|
57
66
|
export function createPainter(color) {
|
package/dist/report.js.map
CHANGED
|
@@ -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 { 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 { displayWidth } from './vendor/spec-core/text/index.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 * The baseline's path as it is typed where the run was started, for the\n * command that re-records it; `baseline.source` when unset. The source reads\n * from the root, and typed in a directory below it, it names another file.\n * Beside the baseline rather than in it, because the JSON report writes the\n * baseline whole.\n */\n readonly recordAs?: string | 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/**\n * Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to TTY.\n *\n * `CI` is not read. It says who started the run and nothing of what the\n * stream draws: a pipeline's log that is a terminal draws colour, spec-brief\n * and spec-guard colour there, and one that does not sets `NO_COLOR`.\n */\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 return environment.isTTY === true;\n}\n\n/**\n * True when ASCII was asked for, or the terminal is unlikely to render\n * box-drawing and arrows.\n *\n * `SPEC_GRAPH_ASCII` asks, and `0`, `false` and a blank do not: each is how a\n * script writes \"off\", and every one of them used to turn ASCII on.\n */\nexport function shouldUseAscii(environment: ColorEnvironment = {}): boolean {\n const env = environment.env ?? process.env;\n const asked = (env['SPEC_GRAPH_ASCII'] ?? '').trim().toLowerCase();\n if (asked !== '' && asked !== '0' && asked !== 'false') 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 // Zero is falsy and never reaches the comparison, so `> 0` and `>= 0` are\n // the same test here.\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 //\n // The fallback is only ever filtered for gone entries, so filling it with\n // anything that is not one counts the same zero.\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 ${options.recordAs ?? 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 // `ok` means no errors, so where it is true the sum below is the warnings\n // alone and `-` in place of `+` asks the same question.\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 // Padded to the columns a terminal draws, not to UTF-16 units: `docs/決策.md`\n // is ten units and twelve columns, so `.padEnd` left the notes beside it two\n // columns out of line.\n const width = Math.max(0, ...diagnostic.related.map((entry) => displayWidth(formatRef(entry.at))));\n for (const entry of diagnostic.related) {\n const reference = formatRef(entry.at);\n const padded = `${reference}${' '.repeat(width - displayWidth(reference))}`;\n lines.push(` ${paint.dim(marks.related)} ${paint.dim(padded)} ${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 // `ok` means no errors, as in the terminal's verdict, so `-` in place of `+`\n // below asks the same question.\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 // Zero never reaches the comparison, as in the terminal report.\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 // The fallback is only filtered for gone entries, as in the terminal report.\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 // Every block above ends in exactly one blank line, so there is only ever one\n // trailing newline for this to strip, and `\\n$` would strip the same.\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, '|').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 // JSON.stringify drops a key whose value is undefined, so always\n // spreading the pair writes the same file; the test is for the reader.\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\n/* -------------------------------------------------------------------------- */\n/* GitHub workflow commands */\n/* -------------------------------------------------------------------------- */\n\n/** A workflow command's message: `%`, and the line breaks that would end the command. */\nfunction escapeData(text: string): string {\n return text.replace(/%/g, '%25').replace(/\\r/g, '%0D').replace(/\\n/g, '%0A');\n}\n\n/** A workflow command's property: as a message, and the `:` and `,` that would end the property. */\nfunction escapeProperty(text: string): string {\n return escapeData(text).replace(/:/g, '%3A').replace(/,/g, '%2C');\n}\n\n/**\n * Findings as GitHub Actions workflow commands, one line each, which a job's\n * log turns into annotations on the pull request's diff with no upload step -\n * what SARIF does through code scanning, for a repository that has none.\n *\n * An error is `error`, a warning `warning` and a note `notice`, as spec-guard\n * writes them. The rule is the title, marked `(strict)` where only `--strict`\n * made it an error, as the Markdown report marks it; the message carries the\n * hint, since a finding without its next action is the half a reader cannot\n * act on. Nothing at all for a clean run.\n */\nexport function formatGithub(\n result: AnalysisResult,\n options: { escalated?: ReadonlySet<AnyRuleId> | undefined } = {},\n): string {\n const escalated = options.escalated ?? EMPTY_RULES;\n return result.diagnostics\n .map((diagnostic) => {\n const title = escalated.has(diagnostic.rule) ? `${diagnostic.rule} (strict)` : diagnostic.rule;\n const place = `file=${escapeProperty(diagnostic.at.file)},line=${diagnostic.at.span.start.line}`;\n return `::${githubLevel(diagnostic.severity)} ${place},title=${escapeProperty(title)}::${escapeData(\n `${diagnostic.message}. ${diagnostic.hint}`,\n )}\\n`;\n })\n .join('');\n}\n\nfunction githubLevel(severity: Severity): 'error' | 'warning' | 'notice' {\n switch (severity) {\n case 'error':\n return 'error';\n case 'warn':\n return 'warning';\n default:\n return 'notice';\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 // Always spreading would write `baseline: undefined`, which JSON.stringify\n // drops, so the test changes nothing but what the line says.\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 //\n // An item is contained by its own document, so its containment would\n // lift onto that document and fall to the reflexive filter below\n // anyway: dropping this filter changes no export, and it stays to\n // say which containment the view keeps.\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 // An edge that did not move, rebuilt, is the same edge: its own\n // `reflexive` already says whether `from` is `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 // `generator: undefined` is dropped by JSON.stringify, so the test\n // decides nothing the file shows.\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 // Anything here that is not an edge between drawn nodes is dropped by the\n // filter formatGraph applies next, so seeding this array changes no export.\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 // Every phase has a fill, `unknown` included, so the fallback is for a\n // phase added to the lattice before it is given a colour, and no graph\n // today reaches it.\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 // formatGraph hands over only edges between the nodes being drawn, and every\n // one of those has an alias.\n for (const edge of edges) {\n lines.push(` ${alias.get(edge.from) as string} -->|${edge.kind}| ${alias.get(edge.to) as string}`);\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 { displayWidth } from './vendor/spec-core/text/index.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 * The baseline's path as it is typed where the run was started, for the\n * command that re-records it; `baseline.source` when unset. The source reads\n * from the root, and typed in a directory below it, it names another file.\n * Beside the baseline rather than in it, because the JSON report writes the\n * baseline whole.\n */\n readonly recordAs?: string | 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/**\n * Honours `NO_COLOR`, `FORCE_COLOR` and `TERM=dumb` before falling back to\n * TTY, as the family reads them (spec-core's ADR-0005): `NO_COLOR` set to\n * anything first; then `FORCE_COLOR`, off for exactly `0` or exactly `false`\n * and on for anything else; then `TERM=dumb`. Either of the first two set to\n * nothing is as unset.\n *\n * `CI` is not read. It says who started the run and nothing of what the\n * stream draws: a pipeline's log that is a terminal draws colour, spec-brief\n * and spec-guard colour there, and one that does not sets `NO_COLOR`.\n */\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 // `0` and `false` are how the convention writes off, as Node and\n // supports-color read them, so each has to win over an attached TTY rather\n // than merely fail to force colour on: `false` used to force it. The two\n // spellings exactly; every other value that is not empty forces colour on.\n const forced = env['FORCE_COLOR'];\n if (forced === '0' || forced === 'false') return false;\n if (forced !== undefined && forced !== '') return true;\n if (env['TERM'] === 'dumb') return false;\n return environment.isTTY === true;\n}\n\n/**\n * True when ASCII was asked for, or the terminal is unlikely to render\n * box-drawing and arrows.\n *\n * `SPEC_GRAPH_ASCII` asks, and `0`, `false` and a blank do not: each is how a\n * script writes \"off\", and every one of them used to turn ASCII on.\n */\nexport function shouldUseAscii(environment: ColorEnvironment = {}): boolean {\n const env = environment.env ?? process.env;\n const asked = (env['SPEC_GRAPH_ASCII'] ?? '').trim().toLowerCase();\n if (asked !== '' && asked !== '0' && asked !== 'false') 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 // Set to nothing is as unset, as for every convention's variable: `WT_SESSION=`\n // is a script clearing it, and used to read as a terminal announcing itself.\n return (env['WT_SESSION'] ?? '') === '' && (env['TERM_PROGRAM'] ?? '') === '';\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 // Zero is falsy and never reaches the comparison, so `> 0` and `>= 0` are\n // the same test here.\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 //\n // The fallback is only ever filtered for gone entries, so filling it with\n // anything that is not one counts the same zero.\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 ${options.recordAs ?? 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 // `ok` means no errors, so where it is true the sum below is the warnings\n // alone and `-` in place of `+` asks the same question.\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 // Padded to the columns a terminal draws, not to UTF-16 units: `docs/決策.md`\n // is ten units and twelve columns, so `.padEnd` left the notes beside it two\n // columns out of line.\n const width = Math.max(0, ...diagnostic.related.map((entry) => displayWidth(formatRef(entry.at))));\n for (const entry of diagnostic.related) {\n const reference = formatRef(entry.at);\n const padded = `${reference}${' '.repeat(width - displayWidth(reference))}`;\n lines.push(` ${paint.dim(marks.related)} ${paint.dim(padded)} ${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 // `ok` means no errors, as in the terminal's verdict, so `-` in place of `+`\n // below asks the same question.\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 // Zero never reaches the comparison, as in the terminal report.\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 // The fallback is only filtered for gone entries, as in the terminal report.\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 // Every block above ends in exactly one blank line, so there is only ever one\n // trailing newline for this to strip, and `\\n$` would strip the same.\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, '|').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 // JSON.stringify drops a key whose value is undefined, so always\n // spreading the pair writes the same file; the test is for the reader.\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\n/* -------------------------------------------------------------------------- */\n/* GitHub workflow commands */\n/* -------------------------------------------------------------------------- */\n\n/** A workflow command's message: `%`, and the line breaks that would end the command. */\nfunction escapeData(text: string): string {\n return text.replace(/%/g, '%25').replace(/\\r/g, '%0D').replace(/\\n/g, '%0A');\n}\n\n/** A workflow command's property: as a message, and the `:` and `,` that would end the property. */\nfunction escapeProperty(text: string): string {\n return escapeData(text).replace(/:/g, '%3A').replace(/,/g, '%2C');\n}\n\n/**\n * Findings as GitHub Actions workflow commands, one line each, which a job's\n * log turns into annotations on the pull request's diff with no upload step -\n * what SARIF does through code scanning, for a repository that has none.\n *\n * An error is `error`, a warning `warning` and a note `notice`, as spec-guard\n * writes them. The rule is the title, marked `(strict)` where only `--strict`\n * made it an error, as the Markdown report marks it; the message carries the\n * hint, since a finding without its next action is the half a reader cannot\n * act on. Nothing at all for a clean run.\n */\nexport function formatGithub(\n result: AnalysisResult,\n options: { escalated?: ReadonlySet<AnyRuleId> | undefined } = {},\n): string {\n const escalated = options.escalated ?? EMPTY_RULES;\n return result.diagnostics\n .map((diagnostic) => {\n const title = escalated.has(diagnostic.rule) ? `${diagnostic.rule} (strict)` : diagnostic.rule;\n const place = `file=${escapeProperty(diagnostic.at.file)},line=${diagnostic.at.span.start.line}`;\n return `::${githubLevel(diagnostic.severity)} ${place},title=${escapeProperty(title)}::${escapeData(\n `${diagnostic.message}. ${diagnostic.hint}`,\n )}\\n`;\n })\n .join('');\n}\n\nfunction githubLevel(severity: Severity): 'error' | 'warning' | 'notice' {\n switch (severity) {\n case 'error':\n return 'error';\n case 'warn':\n return 'warning';\n default:\n return 'notice';\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 // Always spreading would write `baseline: undefined`, which JSON.stringify\n // drops, so the test changes nothing but what the line says.\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 //\n // An item is contained by its own document, so its containment would\n // lift onto that document and fall to the reflexive filter below\n // anyway: dropping this filter changes no export, and it stays to\n // say which containment the view keeps.\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 // An edge that did not move, rebuilt, is the same edge: its own\n // `reflexive` already says whether `from` is `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 // `generator: undefined` is dropped by JSON.stringify, so the test\n // decides nothing the file shows.\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 // Anything here that is not an edge between drawn nodes is dropped by the\n // filter formatGraph applies next, so seeding this array changes no export.\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 // Every phase has a fill, `unknown` included, so the fallback is for a\n // phase added to the lattice before it is given a colour, and no graph\n // today reaches it.\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 // formatGraph hands over only edges between the nodes being drawn, and every\n // one of those has an alias.\n for (const edge of edges) {\n lines.push(` ${alias.get(edge.from) as string} -->|${edge.kind}| ${alias.get(edge.to) as string}`);\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/package.json
CHANGED