@descent-vtt/spec-graph 0.9.1 → 0.9.3

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 (49) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +162 -15
  3. package/dist/baseline.js +6 -0
  4. package/dist/baseline.js.map +1 -1
  5. package/dist/cli.d.ts +1 -1
  6. package/dist/cli.js +50 -17
  7. package/dist/cli.js.map +1 -1
  8. package/dist/config.d.ts +3 -3
  9. package/dist/config.js +16 -8
  10. package/dist/config.js.map +1 -1
  11. package/dist/diff.js +14 -0
  12. package/dist/diff.js.map +1 -1
  13. package/dist/directives.js +9 -6
  14. package/dist/directives.js.map +1 -1
  15. package/dist/extract.js +120 -57
  16. package/dist/extract.js.map +1 -1
  17. package/dist/glob.js +28 -16
  18. package/dist/glob.js.map +1 -1
  19. package/dist/graph.d.ts +2 -1
  20. package/dist/graph.js +10 -1
  21. package/dist/graph.js.map +1 -1
  22. package/dist/identity.d.ts +6 -0
  23. package/dist/identity.js +68 -68
  24. package/dist/identity.js.map +1 -1
  25. package/dist/lifecycle.js +17 -11
  26. package/dist/lifecycle.js.map +1 -1
  27. package/dist/report.js +34 -5
  28. package/dist/report.js.map +1 -1
  29. package/dist/resolve.js +40 -14
  30. package/dist/resolve.js.map +1 -1
  31. package/dist/rules.d.ts +8 -0
  32. package/dist/rules.js +83 -16
  33. package/dist/rules.js.map +1 -1
  34. package/dist/runner.js +22 -4
  35. package/dist/runner.js.map +1 -1
  36. package/dist/sections.d.ts +9 -0
  37. package/dist/sections.js +60 -9
  38. package/dist/sections.js.map +1 -1
  39. package/dist/select.d.ts +18 -2
  40. package/dist/select.js +46 -16
  41. package/dist/select.js.map +1 -1
  42. package/dist/source.js +2 -0
  43. package/dist/source.js.map +1 -1
  44. package/dist/state.js +46 -12
  45. package/dist/state.js.map +1 -1
  46. package/dist/yaml.js +11 -3
  47. package/dist/yaml.js.map +1 -1
  48. package/package.json +6 -3
  49. package/src/vendor/spec-core/README.md +0 -8
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ import { DiffInputError, diffExports, formatDiffJson, formatDiffMarkdown, format
15
15
  import { isGlob, underRoot } from './glob.js';
16
16
  import { analyse, DEFAULT_PATTERNS, withDiagnostics } from './runner.js';
17
17
  import { formatGitlab, formatGraph, formatJson, formatMarkdown, formatReport, formatSarif, shouldUseAscii, shouldUseColor, } from './report.js';
18
- import { DEFAULT_SEVERITIES, resolveStrict, RULE_DECISIONS, RULE_DESCRIPTIONS, RULE_IDS, RULE_QUERIES, } from './rules.js';
18
+ import { DEFAULT_SEVERITIES, resolveStrict, RULE_DECISIONS, decisionUrl, RULE_DESCRIPTIONS, RULE_IDS, RULE_QUERIES, } from './rules.js';
19
19
  import { isAbsolutePath, toPosix } from './paths.js';
20
20
  import { formatRef } from './source.js';
21
21
  import { execute, parseQuery, QueryError, renderMatch } from './select.js';
@@ -142,10 +142,12 @@ CONFIGURATION
142
142
  "historyPatterns": ["**/JOURNAL_*.md", "archive/**"],
143
143
  "baseline": ".spec-graph-baseline.json",
144
144
  "severities": { "self-reference": "off" },
145
- "strict": true }
145
+ "strict": true,
146
+ "maxRelated": 3 }
146
147
 
147
148
  A flag always wins over the file, and list flags add to it rather than
148
- replacing it.
149
+ replacing it. maxRelated has no flag: it caps how many related locations one
150
+ finding lists, 8 unless set, and 0 lists none.
149
151
 
150
152
  A problem in that file stops the run with exit 2, named on stderr: invalid
151
153
  JSON, an unknown key, a rule that does not compile. A configuration that did
@@ -211,12 +213,10 @@ const SEVERITIES = ['error', 'warn', 'info', 'off'];
211
213
  export function parseArgs(argv, cwd) {
212
214
  const args = [...argv];
213
215
  let command = 'check';
214
- if (args.length > 0 && !(args[0].startsWith('-'))) {
215
- const first = args[0];
216
- if (first === 'check' || first === 'query' || first === 'graph' || first === 'rules' || first === 'diff') {
217
- command = first;
218
- args.shift();
219
- }
216
+ const first = args[0];
217
+ if (first === 'check' || first === 'query' || first === 'graph' || first === 'rules' || first === 'diff') {
218
+ command = first;
219
+ args.shift();
220
220
  }
221
221
  const patterns = [];
222
222
  const ignore = [];
@@ -480,6 +480,8 @@ export async function main(io = {}) {
480
480
  options = parseArgs(argv, cwd);
481
481
  }
482
482
  catch (error) {
483
+ // parseArgs throws nothing but a UsageError for any argv, so no test can
484
+ // tell this check from `true`: the rethrow is for a bug in the parser.
483
485
  if (error instanceof UsageError) {
484
486
  err(`spec-graph: ${error.message}\n`);
485
487
  return EXIT_ERROR;
@@ -549,7 +551,7 @@ export async function main(io = {}) {
549
551
  err(`spec-graph: unknown rule "${wanted}"\n known rules: ${RULE_IDS.join(', ')}\n ${knownProjectRules(projectRules)}\n`);
550
552
  return EXIT_ERROR;
551
553
  }
552
- out(renderRules(options.verbose, projectRules, wanted ?? null, loaded.source));
554
+ out(renderRules(options.verbose, await readVersion(), projectRules, wanted ?? null, loaded.source));
553
555
  return EXIT_OK;
554
556
  }
555
557
  const patterns = options.patterns.length > 0 ? options.patterns.map((pattern) => anchor(here, pattern)) : (file.patterns ?? DEFAULT_PATTERNS);
@@ -562,6 +564,11 @@ export async function main(io = {}) {
562
564
  // .gitignore line does, so it means the same thing wherever it was typed.
563
565
  // A path or a glob is matched against the repository-relative path, and
564
566
  // leaving that one alone would make it silently match nothing.
567
+ //
568
+ // A stray entry in one of the empty fallbacks below changes a run only if
569
+ // it matches a path, a target or a family some corpus has, so the mutants
570
+ // that plant one survive every corpus but one built for them - except in
571
+ // `families`, where any entry is an allowlist.
565
572
  ignore: [...(file.ignore ?? []), ...options.ignore.map((pattern) => anchorPath(here, pattern))],
566
573
  ignoreReferences: [...(file.ignoreReferences ?? []), ...options.ignoreReferences],
567
574
  families: [...(file.families ?? []), ...options.families],
@@ -569,7 +576,7 @@ export async function main(io = {}) {
569
576
  historyPatterns: [...(file.historyPatterns ?? []), ...options.historyPatterns.map((pattern) => anchorPath(here, pattern))],
570
577
  severities,
571
578
  projectRules,
572
- ...(file.maxRelated !== undefined ? { maxRelated: file.maxRelated } : {}),
579
+ maxRelated: file.maxRelated,
573
580
  };
574
581
  // Named the way the reader would have to type it, because a discovered
575
582
  // configuration is often not the one in front of them.
@@ -626,6 +633,8 @@ export async function main(io = {}) {
626
633
  queries = [parseQuery(selector)];
627
634
  }
628
635
  catch (error) {
636
+ // Every selector that fails to parse fails as a QueryError, so no
637
+ // test can tell this check from `true`.
629
638
  if (error instanceof QueryError) {
630
639
  err(renderQueryError(selector, error));
631
640
  return EXIT_ERROR;
@@ -634,6 +643,8 @@ export async function main(io = {}) {
634
643
  }
635
644
  }
636
645
  const matches = union(result.graph, queries);
646
+ // renderMatches asks only whether this is 'json', so the other word is a
647
+ // name for the reader and emptying it changes nothing.
637
648
  out(renderMatches(matches, options.format === 'json' ? 'json' : 'human', result.graph.nodes.size));
638
649
  return matches.length > 0 ? EXIT_OK : EXIT_FAILED;
639
650
  }
@@ -645,6 +656,8 @@ export async function main(io = {}) {
645
656
  const text = formatBaseline(result.graph, result.diagnostics);
646
657
  try {
647
658
  const { writeFile } = await import('node:fs/promises');
659
+ // Node writes a string as UTF-8 when the encoding is empty too, so
660
+ // emptying this literal writes the same bytes.
648
661
  await writeFile(underRoot(root, anchor(here, options.recordBaseline)), text, 'utf8');
649
662
  }
650
663
  catch (error) {
@@ -693,7 +706,7 @@ export async function main(io = {}) {
693
706
  // stdout only for a human - the structured formats carry the same rows
694
707
  // inside the document, where a stray line is the difference between
695
708
  // parsing and not.
696
- if (options.format === 'human' && (options.verbose || (ratchet && outcome.stale.length > 0))) {
709
+ if (options.format === 'human' && (options.verbose || ratchet)) {
697
710
  for (const entry of outcome.stale) {
698
711
  const subject = entry.subject === '' ? '' : ` "${entry.subject}"`;
699
712
  const why = entry.reason === 'gone' ? ` - ${entry.document} is not in this corpus` : '';
@@ -702,14 +715,13 @@ export async function main(io = {}) {
702
715
  }
703
716
  }
704
717
  const looseBaseline = note !== undefined && note.ratchet && note.stale > 0;
705
- const baselineNote = note === undefined ? {} : { baseline: note };
706
- const reporterOptions = { verbose: options.verbose, max: options.max, escalated, ...baselineNote };
718
+ const reporterOptions = { verbose: options.verbose, max: options.max, escalated, baseline: note };
707
719
  out(options.format === 'sarif'
708
720
  ? formatSarif(reported, reported.graph, { version: await readVersion(), escalated, projectRules })
709
721
  : options.format === 'gitlab'
710
722
  ? formatGitlab(reported, { escalated })
711
723
  : options.format === 'json'
712
- ? formatJson(reported, { escalated, ...baselineNote })
724
+ ? formatJson(reported, { escalated, baseline: note })
713
725
  : options.format === 'markdown'
714
726
  ? formatMarkdown(reported, reporterOptions)
715
727
  : `${formatReport(reported, { color, ascii, ...reporterOptions })}\n`);
@@ -733,6 +745,9 @@ export async function main(io = {}) {
733
745
  */
734
746
  function below(root, from) {
735
747
  const start = toPosix(from).replace(/[/]+$/, '');
748
+ // The prefix test only guards a root that is neither `start` nor above it,
749
+ // which nothing returns; for `start` itself, slicing past its end is `''`
750
+ // too, so emptying the prefix changes nothing a run can reach.
736
751
  return start.startsWith(`${root}/`) ? start.slice(root.length + 1) : '';
737
752
  }
738
753
  /**
@@ -775,6 +790,9 @@ function knownProjectRules(projectRules) {
775
790
  * this command what a rule matches answers with the set `check` reports on.
776
791
  */
777
792
  function union(graph, queries) {
793
+ // `execute` already returns each path of nodes once, keyed the way this is,
794
+ // so one selector needs no second pass and sending it through one anyway
795
+ // returns the same matches.
778
796
  if (queries.length === 1)
779
797
  return execute(graph, queries[0]);
780
798
  const seen = new Set();
@@ -790,7 +808,7 @@ function union(graph, queries) {
790
808
  }
791
809
  return matches;
792
810
  }
793
- function renderRules(explain, projectRules = [], only = null, configSource = null) {
811
+ function renderRules(explain, version, projectRules, only, configSource) {
794
812
  // A project rule is described by the selector it is, because that is what it
795
813
  // is - its message is a template, and a template is not a description.
796
814
  const rows = [
@@ -799,13 +817,15 @@ function renderRules(explain, projectRules = [], only = null, configSource = nul
799
817
  severity: DEFAULT_SEVERITIES[id],
800
818
  description: RULE_DESCRIPTIONS[id],
801
819
  query: RULE_QUERIES[id],
802
- decided: RULE_DECISIONS[id],
820
+ decided: decisionUrl(RULE_DECISIONS[id], version),
803
821
  })),
804
822
  ...projectRules.map((rule) => ({
805
823
  id: rule.id,
806
824
  severity: rule.severity,
807
825
  description: rule.sources[0],
808
826
  query: rule.sources.slice(1).join(' | ') || undefined,
827
+ // A project rule only exists because a file declared it, so the source
828
+ // is never null here and the first branch is for the type alone.
809
829
  decided: configSource === null ? `rules.${rule.name}` : `${configSource}: rules.${rule.name}`,
810
830
  })),
811
831
  ];
@@ -883,6 +903,8 @@ async function runDiff(paths, cwd, format, out, err) {
883
903
  for (const path of paths) {
884
904
  let raw;
885
905
  try {
906
+ // Without the encoding this is a Buffer, which JSON.parse decodes as
907
+ // UTF-8 all the same - so emptying the literal parses the same export.
886
908
  raw = await readFile(resolve(cwd, path), 'utf8');
887
909
  }
888
910
  catch (error) {
@@ -893,6 +915,8 @@ async function runDiff(paths, cwd, format, out, err) {
893
915
  sides.push(parseGraphExport(raw, path));
894
916
  }
895
917
  catch (error) {
918
+ // Every input parseGraphExport refuses, it refuses as a DiffInputError;
919
+ // the rethrow is for a bug in it, which no file reaches.
896
920
  if (!(error instanceof DiffInputError))
897
921
  throw error;
898
922
  err(`spec-graph: ${error.message}\n`);
@@ -904,6 +928,15 @@ async function runDiff(paths, cwd, format, out, err) {
904
928
  out(format === 'json' ? formatDiffJson(diff) : format === 'markdown' ? formatDiffMarkdown(diff) : formatDiffText(diff));
905
929
  return EXIT_OK;
906
930
  }
931
+ /**
932
+ * The version in the package's own manifest.
933
+ *
934
+ * The guards and the placeholder are for a manifest that is missing or
935
+ * malformed, and the one this reads always parses and always has a version, so
936
+ * no test reaches them without replacing the file the package ships - and the
937
+ * same parse without the encoding reads a Buffer, which JSON.parse decodes as
938
+ * UTF-8 all the same.
939
+ */
907
940
  async function readVersion() {
908
941
  try {
909
942
  const { readFile } = await import('node:fs/promises');
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The command line.\n *\n * Five verbs, because there are five questions worth asking of a specification\n * graph: is it consistent (`check`), what does it contain (`query`), what does\n * it look like (`graph`), what will you check for me (`rules`), and what did a\n * change do to it (`diff`).\n *\n * Exit codes are the contract with CI: `0` clean, `1` findings, `2` the tool\n * itself could not run. A usage mistake never masquerades as a passing build.\n */\n\nimport {\n applyBaseline,\n EMPTY_BASELINE,\n formatBaseline,\n parseBaseline,\n type Baseline,\n type StaleEntry,\n} from './baseline.js';\nimport { discoverConfig, loadConfig, type SpecGraphConfig } from './config.js';\nimport {\n DiffInputError,\n diffExports,\n formatDiffJson,\n formatDiffMarkdown,\n formatDiffText,\n parseGraphExport,\n type GraphExport,\n} from './diff.js';\nimport { isGlob, underRoot } from './glob.js';\nimport { analyse, DEFAULT_PATTERNS, withDiagnostics, type AnalyseOptions, type AnalysisResult } from './runner.js';\nimport {\n formatGitlab,\n formatGraph,\n formatJson,\n formatMarkdown,\n formatReport,\n formatSarif,\n shouldUseAscii,\n shouldUseColor,\n type GraphFormat,\n} from './report.js';\nimport type { ProjectRule } from './project-rules.js';\nimport {\n DEFAULT_SEVERITIES,\n resolveStrict,\n RULE_DECISIONS,\n RULE_DESCRIPTIONS,\n RULE_IDS,\n RULE_QUERIES,\n} from './rules.js';\nimport { isAbsolutePath, toPosix } from './paths.js';\nimport { formatRef } from './source.js';\nimport { execute, parseQuery, QueryError, renderMatch, type Match, type QuerySpec } from './select.js';\nimport { isProjectRule, type AnyRuleId, type RuleId, type Severity, type SpecNode } from './types.js';\n\nexport const EXIT_OK = 0;\nexport const EXIT_FAILED = 1;\nexport const EXIT_ERROR = 2;\n\nexport class UsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UsageError';\n }\n}\n\nexport type Command = 'check' | 'query' | 'graph' | 'rules' | 'diff';\n\nexport interface CliOptions {\n readonly command: Command;\n readonly patterns: readonly string[];\n readonly root: string;\n /**\n * Whether `--root` was given.\n *\n * When it was, the caller has named the root and configuration is read from\n * exactly there. When it was not, the root is discovered - which is a\n * different question from what the root currently is. See ADR-0018.\n */\n readonly rootExplicit: boolean;\n readonly ignore: readonly string[];\n /** Reference targets to leave unreported when they do not resolve. */\n readonly ignoreReferences: readonly string[];\n /** Families a bare identifier may name. Empty means any family in the corpus. */\n readonly families: readonly string[];\n /** Families that are never citations. */\n readonly ignoreFamilies: readonly string[];\n /** Files that log what was decided rather than deciding it. */\n readonly historyPatterns: readonly string[];\n /** Accepted-debt file to read. `null` means none was asked for. */\n readonly baseline: string | null;\n /** Where to write the current findings as accepted debt. */\n readonly recordBaseline: string | null;\n /**\n * Fail when the baseline allows something that no longer happens.\n *\n * The other side of the ratchet, and off by default for the reason ADR-0012\n * gives: failing a build because somebody fixed something is a strange way to\n * encourage them. A team that has decided its debt only goes one way asks for\n * it explicitly, and then a dead exemption cannot outlive the defect.\n */\n readonly ratchet: boolean;\n /** Skip the repository configuration file entirely. */\n readonly noConfig: boolean;\n readonly format: 'human' | 'json' | 'sarif' | 'markdown' | 'gitlab';\n readonly graphFormat: GraphFormat;\n readonly severities: Partial<Record<AnyRuleId, Severity>>;\n readonly color: boolean | null;\n readonly ascii: boolean | null;\n readonly verbose: boolean;\n readonly documentsOnly: boolean;\n readonly max: number;\n readonly maxWarnings: number;\n /** Raise every warning to an error. Explicit `--rule` overrides still win. */\n readonly strict: boolean;\n readonly selector: string | null;\n readonly help: boolean;\n readonly version: boolean;\n}\n\nexport interface CliIO {\n readonly argv?: readonly string[] | undefined;\n readonly cwd?: string | undefined;\n readonly stdout?: ((text: string) => void) | undefined;\n readonly stderr?: ((text: string) => void) | undefined;\n readonly env?: Readonly<Record<string, string | undefined>> | undefined;\n readonly isTTY?: boolean | undefined;\n}\n\nexport const HELP = `spec-graph - turn Markdown specifications into a verifiable graph\n\nUSAGE\n spec-graph [check] [patterns...] [options]\n spec-graph query <selector|project:rule> [patterns...] [options]\n spec-graph graph [patterns...] [--graph-format dot|mermaid|json]\n spec-graph rules [rule-id] [--explain]\n spec-graph diff <before.json> <after.json> [--format human|json|markdown]\n\nCOMMANDS\n check Validate the specification graph. The default.\n query Run a selector - or a registered project rule, by its id - and\n print the matching paths.\n graph Export the graph for Graphviz, Mermaid, or another tool.\n rules List the diagnostics that will run, built in and project. Name one\n to see only that one; --explain adds its selector and the ADR that\n decided it.\n diff Compare two graph exports: documents added, removed, moved or\n accepted; relations added or removed; and obligations resolved or\n reopened where they can be told apart. Make both exports with the\n same spec-graph. Exits 0 whether anything changed or not.\n\nOPTIONS\n --root <dir> Directory the patterns resolve against. Without it,\n .spec-graph.json is looked for in the working\n directory and then upward as far as the repository,\n and the directory holding it becomes the root - so a\n run from a subdirectory reports what a run from the\n top reports. Paths typed on the command line stay\n relative to where they were typed.\n --ignore <glob> Skip paths. Repeatable.\n --ignore-ref <glob> Do not report these reference targets when they fail\n to resolve, for repositories where [[...]] tags a\n concept rather than naming a file. Repeatable.\n Suppresses findings only, never edges.\n --family <name> Families a bare identifier in prose may name. When\n given, everything else stays prose. Repeatable.\n --ignore-family <name> Families that are never citations - RFC when the repo\n cites RFC 2119 and keeps its own RFCs. Repeatable.\n --history <glob> Files that log what was decided rather than deciding\n it - journals, changelogs, minutes. Their links are\n still checked; their obligations are not. Repeatable.\n --baseline <file> Accept the findings recorded in this file and report\n only what is new since. The file has to be there: a\n path that reads nothing accepts nothing and says so\n nowhere. A \"baseline\" in the configuration may name a\n file not recorded yet; a path typed here may not.\n --record-baseline <f> Write today's findings to this file as accepted debt,\n and exit 0 without judging them.\n --ratchet Also fail when a baseline entry no longer occurs, so\n a paid-off exemption cannot outlive the defect.\n --no-config Ignore .spec-graph.json and the package.json key.\n --format <fmt> human, json, sarif, gitlab or markdown. sarif is the\n interchange format GitHub code scanning and editors\n already read, and gitlab the Code Quality report a\n GitLab merge request reads, both for check; markdown\n is a table for a pull-request comment or\n $GITHUB_STEP_SUMMARY, for check or diff\n (default: human)\n --graph-format <fmt> dot, mermaid or json (default: dot)\n --documents-only Leave items out of the exported graph\n --rule <id>=<severity> Override one rule: error, warn, info or off. A project\n rule is named in full: project:no-draft-dependency.\n Repeatable.\n --max <n> Show at most n findings (0 = no limit)\n --max-warnings <n> Fail when warnings exceed n (default: no limit)\n --strict Raise every warning to an error. An explicit --rule\n still wins, so --strict --rule x=warn exempts x.\n --color / --no-color Force colour on or off\n --ascii Use ASCII glyphs only\n --verbose Include parse problems, per-file detail, and every\n reference --ignore-ref or --ignore-family silenced\n -h, --help Show this help\n -v, --version Show the version\n\nSELECTORS\n A selector is a path through the graph.\n\n item[openness=open] -delegates-to-> document[phase=retired]\n document[phase=active] -assumes-> document[phase=retired]\n document =supersedes=> document\n *[path^=docs/adr] -contains-> item[state=accepted-debt]\n\n Node types: document, item, * (any)\n Attributes: id, kind, title, path, file, line, phase, status, receptivity,\n alias, document, state (or disposition), openness, section,\n text, body, evidence, conflicted, fm.<front-matter-key>\n Operators: = != ^= $= *= ~= and [attr] for \"is present\"\n ~= is a regular expression, matched by an automaton that cannot\n backtrack: linear in the subject, whatever the pattern. It reads\n the usual syntax minus backreferences and lookaround, which are\n not regular - both are refused when the selector is read, with\n the character pointed at\n Relations: -kind-> <-kind- =kind=> <=kind= (= forms are transitive)\n\nEXIT CODES\n 0 clean\n 1 findings at error severity (or over --max-warnings)\n 2 the tool could not run\n\nCONFIGURATION\n Anything repeated on every run belongs in the repository rather than in the\n command. spec-graph reads the first of these that exists:\n\n .spec-graph.json, spec-graph.config.json, or a \"spec-graph\" key in\n package.json\n\n { \"patterns\": [\"docs/**/*.md\"],\n \"ignoreReferences\": [\"trap *\"],\n \"ignoreFamilies\": [\"RFC\"],\n \"historyPatterns\": [\"**/JOURNAL_*.md\", \"archive/**\"],\n \"baseline\": \".spec-graph-baseline.json\",\n \"severities\": { \"self-reference\": \"off\" },\n \"strict\": true }\n\n A flag always wins over the file, and list flags add to it rather than\n replacing it.\n\n A problem in that file stops the run with exit 2, named on stderr: invalid\n JSON, an unknown key, a rule that does not compile. A configuration that did\n not load checks a different repository than the one configured, and would\n report that one as consistent. --no-config runs on defaults instead.\n\nPROJECT RULES\n A convention spec-graph never anticipated is a selector plus a sentence, and\n belongs in the same file. Every rule declared here runs beside the built-ins\n and is reported, baselined, escalated by --strict and silenced by --rule in\n exactly the same way.\n\n { \"rules\": {\n \"no-draft-dependency\": {\n \"query\": \"document[phase=active] -depends-on-> document[phase=draft]\",\n \"message\": \"{0} depends on {1}, which is still a draft\",\n \"hint\": \"wait for {1} to be accepted, or drop it from {0.path}\",\n \"severity\": \"error\" } } }\n\n query One selector, or a list of them read as a union.\n message The headline. {0} is the first node on the path, {1} the next;\n {1.phase} and {0.fm.owner} read any selector attribute.\n hint The next action. Optional, and templated the same way.\n severity error, warn, info or off. Defaults to warn - a rule a team has\n just written has not yet earned the right to fail their build.\n\n The id is the name with project: in front, which is why it can never collide\n with a built-in. A selector that does not parse, or a {2} the query can never\n reach, is reported when the file is read rather than found missing later.\n\n To see what one matches without copying its selector out of the file:\n\n spec-graph query project:no-draft-dependency --verbose\n\nADOPTING THIS ON AN OLD REPOSITORY\n Record what is already wrong, then report only what happens next:\n\n spec-graph check --record-baseline .spec-graph-baseline.json\n git add .spec-graph-baseline.json\n\n The file is keyed by specification and citation, not by line number, so it\n survives edits, moves and renames. Findings that stop occurring are reported\n so the file can be tightened; nothing new gets in.\n\nEXAMPLES\n spec-graph \"docs/**/*.md\"\n spec-graph check --rule self-reference=off --format json\n spec-graph query 'item[openness=open] -delegates-to-> document[phase=retired]'\n spec-graph check --ignore-ref \"trap *\" # [[trap 55]] tags a concept, not a file\n spec-graph graph --documents-only --graph-format mermaid > graph.mmd\n spec-graph check --history \"**/JOURNAL_*.md\" # a log is not a specification\n spec-graph check --baseline .spec-graph-baseline.json\n spec-graph rules --explain # including this repository's own\n spec-graph rules ghost-handover --explain # and why it exists\n spec-graph check --rule project:no-draft-dependency=off\n spec-graph query project:no-draft-dependency # what does that rule match?\n spec-graph check --format markdown >> \"$GITHUB_STEP_SUMMARY\"\n spec-graph check --format gitlab > gl-code-quality-report.json\n spec-graph diff base.json head.json --format markdown >> \"$GITHUB_STEP_SUMMARY\"\n`;\n\nconst SEVERITIES: readonly Severity[] = ['error', 'warn', 'info', 'off'];\n\n/** Parses argv into options. Throws {@link UsageError} on anything malformed. */\nexport function parseArgs(argv: readonly string[], cwd: string): CliOptions {\n const args = [...argv];\n let command: Command = 'check';\n\n if (args.length > 0 && !((args[0] as string).startsWith('-'))) {\n const first = args[0] as string;\n if (first === 'check' || first === 'query' || first === 'graph' || first === 'rules' || first === 'diff') {\n command = first;\n args.shift();\n }\n }\n\n const patterns: string[] = [];\n const ignore: string[] = [];\n const ignoreReferences: string[] = [];\n const families: string[] = [];\n const ignoreFamilies: string[] = [];\n const historyPatterns: string[] = [];\n let noConfig = false;\n const severities: Partial<Record<AnyRuleId, Severity>> = {};\n let root = cwd;\n let rootExplicit = false;\n let format: CliOptions['format'] = 'human';\n let graphFormat: GraphFormat = 'dot';\n let color: boolean | null = null;\n let ascii: boolean | null = null;\n let verbose = false;\n let documentsOnly = false;\n let max = 0;\n let maxWarnings = -1;\n let strict = false;\n let baseline: string | null = null;\n let ratchet = false;\n let recordBaseline: string | null = null;\n let selector: string | null = null;\n let help = false;\n let version = false;\n\n const next = (flag: string, index: number): string => {\n const value = args[index + 1];\n if (value === undefined) throw new UsageError(`${flag} needs a value`);\n return value;\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i] as string;\n\n if (arg === '--') {\n patterns.push(...args.slice(i + 1));\n break;\n }\n\n if (!arg.startsWith('-')) {\n if (command === 'query' && selector === null) selector = arg;\n else patterns.push(arg);\n continue;\n }\n\n switch (arg) {\n case '-h':\n case '--help':\n help = true;\n break;\n case '-v':\n case '--version':\n version = true;\n break;\n case '--verbose':\n verbose = true;\n break;\n case '--color':\n color = true;\n break;\n case '--no-color':\n color = false;\n break;\n case '--ascii':\n ascii = true;\n break;\n case '--documents-only':\n documentsOnly = true;\n break;\n case '--strict':\n strict = true;\n break;\n case '--ratchet':\n ratchet = true;\n break;\n case '--explain':\n verbose = true;\n break;\n case '--root':\n root = next(arg, i);\n rootExplicit = true;\n i += 1;\n break;\n case '--ignore':\n ignore.push(next(arg, i));\n i += 1;\n break;\n case '--ignore-ref':\n ignoreReferences.push(next(arg, i));\n i += 1;\n break;\n case '--family':\n families.push(next(arg, i));\n i += 1;\n break;\n case '--ignore-family':\n ignoreFamilies.push(next(arg, i));\n i += 1;\n break;\n case '--history':\n historyPatterns.push(next(arg, i));\n i += 1;\n break;\n case '--baseline':\n baseline = next(arg, i);\n i += 1;\n break;\n case '--record-baseline':\n recordBaseline = next(arg, i);\n i += 1;\n break;\n case '--no-config':\n noConfig = true;\n break;\n case '--format': {\n const value = next(arg, i);\n if (value !== 'human' && value !== 'json' && value !== 'sarif' && value !== 'markdown' && value !== 'gitlab') {\n throw new UsageError(`--format must be human, json, sarif, markdown or gitlab, got \"${value}\"`);\n }\n format = value;\n i += 1;\n break;\n }\n case '--graph-format': {\n const value = next(arg, i);\n if (value !== 'dot' && value !== 'mermaid' && value !== 'json') {\n throw new UsageError(`--graph-format must be dot, mermaid or json, got \"${value}\"`);\n }\n graphFormat = value;\n i += 1;\n break;\n }\n case '--rule': {\n const value = next(arg, i);\n const equals = value.indexOf('=');\n if (equals === -1) throw new UsageError(`--rule expects <id>=<severity>, got \"${value}\"`);\n const id = value.slice(0, equals) as AnyRuleId;\n const level = value.slice(equals + 1) as Severity;\n // A project rule is taken on its namespace here and checked for real\n // once the configuration defining it has been read: arguments are\n // parsed before any file is opened, and a flag has to be usable on that\n // first pass whatever the repository turns out to declare.\n if (!RULE_IDS.includes(id as RuleId) && !isProjectRule(id)) {\n throw new UsageError(`unknown rule \"${id}\"\\n known rules: ${RULE_IDS.join(', ')}`);\n }\n if (!SEVERITIES.includes(level)) {\n throw new UsageError(`unknown severity \"${level}\", expected one of: ${SEVERITIES.join(', ')}`);\n }\n severities[id] = level;\n i += 1;\n break;\n }\n case '--max': {\n max = parseCount(arg, next(arg, i));\n i += 1;\n break;\n }\n case '--max-warnings': {\n maxWarnings = parseCount(arg, next(arg, i));\n i += 1;\n break;\n }\n default:\n throw new UsageError(`unknown option \"${arg}\"\\n run \"spec-graph --help\" to see the available options`);\n }\n }\n\n // SARIF and GitLab's Code Quality are reports about findings, and only\n // `check` produces those. Falling back to JSON would hand a pipeline something\n // its uploader rejects with a message about a schema rather than about the\n // command that was run. Markdown is for a pull request, which reads a check\n // or a diff.\n if ((format === 'sarif' || format === 'gitlab') && command !== 'check' && !help && !version) {\n throw new UsageError(`--format ${format} reports findings, so it belongs to check, not to ${command}`);\n }\n if (format === 'markdown' && command !== 'check' && command !== 'diff' && !help && !version) {\n throw new UsageError(`--format markdown is a report for a pull request, so it belongs to check or diff, not to ${command}`);\n }\n\n if (command === 'diff' && patterns.length !== 2 && !help && !version) {\n throw new UsageError(\n 'diff compares two graph exports, for example:\\n spec-graph diff base.json head.json\\n (make each with spec-graph graph --graph-format json)',\n );\n }\n\n if (command === 'query' && selector === null && !help && !version) {\n throw new UsageError('query needs a selector, for example:\\n spec-graph query \\'item[openness=open]\\'');\n }\n\n return {\n command,\n patterns,\n root,\n rootExplicit,\n ignore,\n ignoreReferences,\n families,\n ignoreFamilies,\n historyPatterns,\n baseline,\n ratchet,\n recordBaseline,\n noConfig,\n format,\n graphFormat,\n severities,\n color,\n ascii,\n verbose,\n documentsOnly,\n max,\n maxWarnings,\n strict,\n selector,\n help,\n version,\n };\n}\n\nfunction count(n: number, word: string, many?: string): string {\n return `${n} ${n === 1 ? word : (many ?? `${word}s`)}`;\n}\n\ninterface HeldBaseline {\n readonly baseline: Baseline;\n readonly problems: readonly string[];\n /** What stopped the file being read, when something did. */\n readonly unread: { readonly missing: boolean; readonly message: string } | null;\n}\n\n/**\n * Reads a baseline file.\n *\n * Absent and unreadable are different answers, and the caller needs both. A\n * repository that has not recorded a baseline yet declares the path before the\n * file exists, and an empty baseline accepts nothing, which is what that run\n * should report (ADR-0012). Anything else - a directory, a permission, a path\n * that went somewhere unintended - is the tool failing to do what it was told.\n */\nasync function readBaseline(path: string, source: string): Promise<HeldBaseline> {\n let raw: string;\n try {\n const { readFile } = await import('node:fs/promises');\n raw = await readFile(path, 'utf8');\n } catch (error) {\n const failure = error as Error & { code?: string };\n return {\n baseline: EMPTY_BASELINE,\n problems: [],\n unread: { missing: failure.code === 'ENOENT', message: failure.message },\n };\n }\n return { ...parseBaseline(raw, source), unread: null };\n}\n\nfunction parseCount(flag: string, value: string): number {\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || parsed < 0 || String(parsed) !== value.trim()) {\n throw new UsageError(`${flag} expects a non-negative whole number, got \"${value}\"`);\n }\n return parsed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Entry point */\n/* -------------------------------------------------------------------------- */\n\n/** Runs the CLI and returns the process exit code. Never throws. */\nexport async function main(io: CliIO = {}): Promise<number> {\n const argv = io.argv ?? process.argv.slice(2);\n const cwd = io.cwd ?? process.cwd();\n const out = io.stdout ?? ((text) => process.stdout.write(text));\n const err = io.stderr ?? ((text) => process.stderr.write(text));\n const env = io.env ?? process.env;\n\n let options: CliOptions;\n try {\n options = parseArgs(argv, cwd);\n } catch (error) {\n if (error instanceof UsageError) {\n err(`spec-graph: ${error.message}\\n`);\n return EXIT_ERROR;\n }\n throw error;\n }\n\n if (options.help) {\n out(HELP);\n return EXIT_OK;\n }\n if (options.version) {\n out(`${await readVersion()}\\n`);\n return EXIT_OK;\n }\n\n // A diff reads two files and nothing else: no configuration and no corpus, so\n // it can compare exports from a checkout it is not running in.\n if (options.command === 'diff') return runDiff(options.patterns as readonly [string, string], cwd, options.format, out, err);\n\n const color = options.color ?? shouldUseColor({ isTTY: io.isTTY, env });\n const ascii = options.ascii ?? shouldUseAscii({ env });\n\n // Configuration is what is true of the repository; a flag is somebody\n // overriding it for one run. So a flag always wins, and lists add rather than\n // replace - a `--ignore-ref` on the command line is one more exclusion, not a\n // decision to throw away the ones the repository already declared.\n //\n // Read before `rules` prints anything, so that command lists the conventions\n // this repository will actually check rather than the ones spec-graph ships.\n const loaded = options.noConfig\n ? { config: {} as SpecGraphConfig, source: null, problems: [], root: options.root }\n : options.rootExplicit\n ? { ...loadConfig(options.root), root: options.root }\n : discoverConfig(options.root);\n for (const problem of loaded.problems) err(`spec-graph: ${problem}\\n`);\n // A configuration that did not load means a run against a different\n // repository than the one configured - other patterns, other rules, other\n // severities - and the verdict printed is about that one. Reporting the\n // problem and carrying on gave a green build with `ok: true` from a file with\n // a typo in it, which is the one answer a checker must never reach by\n // accident, and the same mistake in a `--rule` has always exited 2. The\n // findings are one flag away, and the flag is named. Amends ADR-0010.\n if (loaded.problems.length > 0) {\n err(\n `spec-graph: ${count(loaded.problems.length, 'problem')} in the configuration, so nothing was checked\\n fix it, or run again with --no-config to check on defaults\\n`,\n );\n return EXIT_ERROR;\n }\n const file = loaded.config;\n const projectRules = file.rules ?? [];\n const root = loaded.root;\n // How far the root moved up. Everything a repository declares about itself is\n // relative to the root; everything typed on the command line is relative to\n // where it was typed, and this is what keeps those two readings apart.\n const here = below(root, options.root);\n\n // A `--rule` naming a project rule that does not exist is a flag that\n // silently does nothing, and nothing in the output would distinguish that\n // from a rule that ran and found none.\n for (const id of Object.keys(options.severities)) {\n if (!isProjectRule(id as AnyRuleId) || projectRules.some((rule) => rule.id === id)) continue;\n err(`spec-graph: unknown rule \"${id}\"\\n ${knownProjectRules(projectRules)}\\n`);\n return EXIT_ERROR;\n }\n\n if (options.command === 'rules') {\n // The one positional argument `rules` can take is a rule id: this command\n // reads no files, so a pattern here would be a word with nowhere to go.\n const wanted = options.patterns[0];\n if (wanted !== undefined && !RULE_IDS.includes(wanted as RuleId) && !projectRules.some((rule) => rule.id === wanted)) {\n err(\n `spec-graph: unknown rule \"${wanted}\"\\n known rules: ${RULE_IDS.join(', ')}\\n ${knownProjectRules(projectRules)}\\n`,\n );\n return EXIT_ERROR;\n }\n out(renderRules(options.verbose, projectRules, wanted ?? null, loaded.source));\n return EXIT_OK;\n }\n\n const patterns =\n options.patterns.length > 0 ? options.patterns.map((pattern) => anchor(here, pattern)) : (file.patterns ?? DEFAULT_PATTERNS);\n const severityOverrides = { ...(file.severities ?? {}), ...options.severities };\n const { severities, escalated } = resolveStrict(\n severityOverrides,\n options.strict || (file.strict ?? false),\n projectRules,\n );\n\n const analyseOptions: AnalyseOptions = {\n root,\n patterns,\n // A bare name prunes a directory of that name at any depth, the way a\n // .gitignore line does, so it means the same thing wherever it was typed.\n // A path or a glob is matched against the repository-relative path, and\n // leaving that one alone would make it silently match nothing.\n ignore: [...(file.ignore ?? []), ...options.ignore.map((pattern) => anchorPath(here, pattern))],\n ignoreReferences: [...(file.ignoreReferences ?? []), ...options.ignoreReferences],\n families: [...(file.families ?? []), ...options.families],\n ignoreFamilies: [...(file.ignoreFamilies ?? []), ...options.ignoreFamilies],\n historyPatterns: [...(file.historyPatterns ?? []), ...options.historyPatterns.map((pattern) => anchorPath(here, pattern))],\n severities,\n projectRules,\n ...(file.maxRelated !== undefined ? { maxRelated: file.maxRelated } : {}),\n };\n\n // Named the way the reader would have to type it, because a discovered\n // configuration is often not the one in front of them.\n //\n // On stderr, with everything else this run says about itself. stdout is the\n // report, and in three of the four formats it is a document: a line above it\n // made `--verbose --format json` unparseable and handed `--format sarif` to a\n // code-scanning uploader that rejects it over a schema.\n if (options.verbose && loaded.source !== null) {\n const depth = here === '' ? 0 : here.split('/').length;\n err(`configuration: ${'../'.repeat(depth)}${loaded.source}\\n`);\n }\n\n let result;\n try {\n result = await analyse(analyseOptions);\n } catch (error) {\n err(`spec-graph: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n\n if (result.files.length === 0) {\n err(\n `spec-graph: no specifications matched ${\n patterns.map((p) => `\"${p}\"`).join(', ')\n }\\n looked under ${root}\\n`,\n );\n return EXIT_ERROR;\n }\n\n switch (options.command) {\n case 'graph':\n out(\n formatGraph(result.graph, options.graphFormat, {\n documentsOnly: options.documentsOnly,\n generator: { name: 'spec-graph', version: await readVersion() },\n }),\n );\n return EXIT_OK;\n\n case 'query': {\n const selector = options.selector as string;\n let queries: readonly QuerySpec[];\n\n // A registered rule is asked for by name, because by the time this runs\n // it is already compiled and the alternative is copying its selector out\n // of the configuration file by hand. The namespace cannot collide with\n // the grammar: no selector begins with a word and a colon. See ADR-0016.\n if (isProjectRule(selector as AnyRuleId)) {\n const rule = projectRules.find((candidate) => candidate.id === selector);\n if (rule === undefined) {\n err(`spec-graph: unknown rule \"${selector}\"\\n ${knownProjectRules(projectRules)}\\n`);\n return EXIT_ERROR;\n }\n queries = rule.queries;\n // Beside the report rather than inside it, for the reason the\n // configuration line above is: `--format json` is a document.\n if (options.verbose) for (const source of rule.sources) err(`${rule.id}: ${source}\\n`);\n } else {\n try {\n queries = [parseQuery(selector)];\n } catch (error) {\n if (error instanceof QueryError) {\n err(renderQueryError(selector, error));\n return EXIT_ERROR;\n }\n throw error;\n }\n }\n\n const matches = union(result.graph, queries);\n out(renderMatches(matches, options.format === 'json' ? 'json' : 'human', result.graph.nodes.size));\n return matches.length > 0 ? EXIT_OK : EXIT_FAILED;\n }\n\n default: {\n // Recording is not checking. It writes down what is wrong today so that\n // tomorrow can be compared against it, and says nothing about whether\n // today is acceptable - so it reports what it wrote and exits clean.\n if (options.recordBaseline !== null) {\n const text = formatBaseline(result.graph, result.diagnostics);\n try {\n const { writeFile } = await import('node:fs/promises');\n await writeFile(underRoot(root, anchor(here, options.recordBaseline)), text, 'utf8');\n } catch (error) {\n err(`spec-graph: cannot write ${options.recordBaseline}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n const entries = (JSON.parse(text) as Baseline).findings.length;\n out(\n `recorded ${count(result.diagnostics.length, 'finding')} as ${count(entries, 'entry', 'entries')} in ${options.recordBaseline}\\n`,\n );\n return EXIT_OK;\n }\n\n const source = options.baseline === null ? (file.baseline ?? null) : anchor(here, options.baseline);\n const ratchet = options.ratchet || file.ratchet === true;\n let reported = result;\n let note:\n | {\n source: string;\n suppressed: number;\n stale: number;\n ratchet: boolean;\n entries: readonly StaleEntry[];\n }\n | undefined;\n if (source !== null) {\n const held = await readBaseline(underRoot(root, source), source);\n // A path typed on the command line says the file is there for this run.\n // Read as an empty baseline instead, a typo in it reports every accepted\n // finding as new, and passes --ratchet with nothing left to be stale.\n // A path in the configuration is the case ADR-0012 argued for, and only\n // where the file is absent: unreadable is unreadable wherever the path\n // was written.\n if (held.unread !== null && (options.baseline !== null || !held.unread.missing)) {\n err(`spec-graph: cannot read the baseline ${source}: ${held.unread.message}\\n`);\n return EXIT_ERROR;\n }\n // Quiet by default, because a configured path legitimately precedes the\n // first --record-baseline. Under --verbose, where parse problems already\n // go, a path that reads nothing says so rather than accepting nothing.\n if (held.unread !== null && options.verbose) {\n err(`spec-graph: baseline ${source} is not there, so nothing is accepted\\n`);\n }\n for (const problem of held.problems) err(`spec-graph: ${problem}\\n`);\n const outcome = applyBaseline(result.graph, result.diagnostics, held.baseline);\n reported = withDiagnostics(result, outcome.kept);\n note = {\n source,\n suppressed: outcome.suppressed,\n stale: outcome.stale.length,\n ratchet,\n entries: outcome.stale,\n };\n // Listed rather than counted when the run turns on them: a number is\n // enough to know the file has slack, and not enough to strike it. On\n // stdout only for a human - the structured formats carry the same rows\n // inside the document, where a stray line is the difference between\n // parsing and not.\n if (options.format === 'human' && (options.verbose || (ratchet && outcome.stale.length > 0))) {\n for (const entry of outcome.stale) {\n const subject = entry.subject === '' ? '' : ` \"${entry.subject}\"`;\n const why = entry.reason === 'gone' ? ` - ${entry.document} is not in this corpus` : '';\n out(` ${entry.reason}: ${entry.rule} ${entry.document}${subject}${why}\\n`);\n }\n }\n }\n const looseBaseline = note !== undefined && note.ratchet && note.stale > 0;\n\n const baselineNote = note === undefined ? {} : { baseline: note };\n const reporterOptions = { verbose: options.verbose, max: options.max, escalated, ...baselineNote };\n out(\n options.format === 'sarif'\n ? formatSarif(reported, reported.graph, { version: await readVersion(), escalated, projectRules })\n : options.format === 'gitlab'\n ? formatGitlab(reported, { escalated })\n : options.format === 'json'\n ? formatJson(reported, { escalated, ...baselineNote })\n : options.format === 'markdown'\n ? formatMarkdown(reported, reporterOptions)\n : `${formatReport(reported, { color, ascii, ...reporterOptions })}\\n`,\n );\n if (!reported.ok || looseBaseline) return EXIT_FAILED;\n if (options.maxWarnings >= 0 && reported.summary.warnings > options.maxWarnings) return EXIT_FAILED;\n return EXIT_OK;\n }\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Rendering */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Where the working directory sits below the root, or `''` when it is the root.\n *\n * Discovery only ever walks upward, so the root is always a prefix of the\n * directory the command was typed in, and this is a slice rather than path\n * arithmetic.\n */\nfunction below(root: string, from: string): string {\n const start = toPosix(from).replace(/[/]+$/, '');\n return start.startsWith(`${root}/`) ? start.slice(root.length + 1) : '';\n}\n\n/**\n * Re-anchors a path typed in `prefix` so it reads from the root.\n *\n * An absolute path is left alone: it was not relative to anywhere, so moving\n * the root cannot change what it means.\n */\nfunction anchor(prefix: string, value: string): string {\n if (prefix === '' || isAbsolutePath(value)) return value;\n const negated = value.startsWith('!');\n const directories = prefix.split('/');\n let rest = toPosix(negated ? value.slice(1) : value);\n // `../docs` typed one directory down is the root's `docs`. That is arithmetic\n // on two relative paths, and this is the one place both are known; left in\n // the pattern, it reads as a glob climbing out of the root, which is refused.\n // A bare `..` typed in `docs/deep` leaves `docs/`: the directory's contents,\n // which is what it named.\n while (directories.length > 0 && (rest === '..' || rest.startsWith('../'))) {\n directories.pop();\n rest = rest.slice(3);\n }\n const joined = [...directories, rest].join('/');\n return negated ? `!${joined}` : joined;\n}\n\n/** The same, for an ignore, where a bare name is a directory at any depth. */\nfunction anchorPath(prefix: string, pattern: string): string {\n return isGlob(pattern) || pattern.includes('/') ? anchor(prefix, pattern) : pattern;\n}\n\nfunction knownProjectRules(projectRules: readonly ProjectRule[]): string {\n const known = projectRules.map((rule) => rule.id);\n return known.length > 0 ? `project rules here: ${known.join(', ')}` : 'this repository defines no project rules';\n}\n\n/**\n * Runs a list of selectors as one result set.\n *\n * A project rule is a union of its selectors, and a path that two of them both\n * find is one path - the same dedupe `projectFindings` does, so that asking\n * this command what a rule matches answers with the set `check` reports on.\n */\nfunction union(graph: AnalysisResult['graph'], queries: readonly QuerySpec[]): Match[] {\n if (queries.length === 1) return execute(graph, queries[0] as QuerySpec);\n const seen = new Set<string>();\n const matches: Match[] = [];\n for (const spec of queries) {\n for (const match of execute(graph, spec)) {\n const key = match.nodes.map((node) => node.id).join('>');\n if (seen.has(key)) continue;\n seen.add(key);\n matches.push(match);\n }\n }\n return matches;\n}\n\ninterface RuleRow {\n readonly id: string;\n readonly severity: Severity;\n readonly description: string;\n /** The selector, where the rule is one. */\n readonly query: string | undefined;\n /** Where the reasoning is: an ADR, or the file that declared the rule. */\n readonly decided: string;\n}\n\nfunction renderRules(\n explain: boolean,\n projectRules: readonly ProjectRule[] = [],\n only: string | null = null,\n configSource: string | null = null,\n): string {\n // A project rule is described by the selector it is, because that is what it\n // is - its message is a template, and a template is not a description.\n const rows: RuleRow[] = [\n ...RULE_IDS.map((id): RuleRow => ({\n id,\n severity: DEFAULT_SEVERITIES[id],\n description: RULE_DESCRIPTIONS[id],\n query: RULE_QUERIES[id],\n decided: RULE_DECISIONS[id],\n })),\n ...projectRules.map((rule): RuleRow => ({\n id: rule.id,\n severity: rule.severity,\n description: rule.sources[0] as string,\n query: rule.sources.slice(1).join(' | ') || undefined,\n decided: configSource === null ? `rules.${rule.name}` : `${configSource}: rules.${rule.name}`,\n })),\n ];\n\n const shown = only === null ? rows : rows.filter((row) => row.id === only);\n const width = Math.max(...shown.map((row) => row.id.length));\n const lines: string[] = [];\n for (const row of shown) {\n lines.push(`${row.id.padEnd(width)} ${row.severity.padEnd(5)} ${row.description}`);\n if (!explain) continue;\n if (row.query) lines.push(`${' '.repeat(width)} ${row.query}`);\n // Where the decision is written down, rather than a second copy of it. A\n // reader who has just been told their document is inconsistent is entitled\n // to know who decided that and why, and the ADR is the answer.\n lines.push(`${' '.repeat(width)} ${row.decided}`);\n }\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction renderMatches(matches: readonly Match[], format: 'human' | 'json', total: number): string {\n if (format === 'json') {\n return `${JSON.stringify(\n {\n version: 1,\n count: matches.length,\n matches: matches.map((match) => ({\n nodes: match.nodes.map((node) => nodeSummary(node)),\n edges: match.edges.map((edge) => ({\n kind: edge.kind,\n from: edge.from,\n to: edge.to,\n file: edge.declaredAt.file,\n line: edge.declaredAt.span.start.line,\n })),\n })),\n },\n null,\n 2,\n )}\\n`;\n }\n\n if (matches.length === 0) return `no matches (searched ${total} nodes)\\n`;\n\n const lines: string[] = [];\n for (const match of matches) {\n const head = match.nodes[0] as SpecNode;\n const tail = match.nodes[match.nodes.length - 1] as SpecNode;\n lines.push(renderMatch(match));\n lines.push(` ${formatRef(head.at)}${match.nodes.length > 1 ? ` ${formatRef(tail.at)}` : ''}`);\n }\n lines.push(`${matches.length} ${matches.length === 1 ? 'match' : 'matches'}`);\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction nodeSummary(node: SpecNode): Record<string, unknown> {\n return {\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 ...(node.kind === 'document' ? { phase: node.phase } : { state: node.disposition, openness: node.openness }),\n };\n}\n\n/** Points at the exact character of a selector that failed to parse. */\nfunction renderQueryError(selector: string, error: QueryError): string {\n const caret = `${' '.repeat(Math.max(0, error.offset))}^`;\n return `spec-graph: ${error.message}\\n ${selector}\\n ${caret}\\n`;\n}\n\n/**\n * Compares two exports.\n *\n * Exit 0 whether anything changed or not: a diff describes, and `check` gates. A\n * diff that failed on a removed relation would fail every legitimate\n * supersession (ADR-0020).\n */\nasync function runDiff(\n paths: readonly [string, string],\n cwd: string,\n format: CliOptions['format'],\n out: (text: string) => void,\n err: (text: string) => void,\n): Promise<number> {\n const { readFile } = await import('node:fs/promises');\n const { resolve } = await import('node:path');\n const sides: GraphExport[] = [];\n for (const path of paths) {\n let raw: string;\n try {\n raw = await readFile(resolve(cwd, path), 'utf8');\n } catch (error) {\n err(`spec-graph: cannot read ${path}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n try {\n sides.push(parseGraphExport(raw, path));\n } catch (error) {\n if (!(error instanceof DiffInputError)) throw error;\n err(`spec-graph: ${error.message}\\n`);\n return EXIT_ERROR;\n }\n }\n const [before, after] = sides as [GraphExport, GraphExport];\n const diff = diffExports(before, after);\n out(format === 'json' ? formatDiffJson(diff) : format === 'markdown' ? formatDiffMarkdown(diff) : formatDiffText(diff));\n return EXIT_OK;\n}\n\nasync function readVersion(): Promise<string> {\n try {\n const { readFile } = await import('node:fs/promises');\n const url = new URL('../package.json', import.meta.url);\n const parsed: unknown = JSON.parse(await readFile(url, 'utf8'));\n if (typeof parsed === 'object' && parsed !== null && 'version' in parsed) {\n return String((parsed as { version: unknown }).version);\n }\n } catch {\n // Fall through to the placeholder rather than failing `--version`.\n }\n return '0.0.0';\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The command line.\n *\n * Five verbs, because there are five questions worth asking of a specification\n * graph: is it consistent (`check`), what does it contain (`query`), what does\n * it look like (`graph`), what will you check for me (`rules`), and what did a\n * change do to it (`diff`).\n *\n * Exit codes are the contract with CI: `0` clean, `1` findings, `2` the tool\n * itself could not run. A usage mistake never masquerades as a passing build.\n */\n\nimport {\n applyBaseline,\n EMPTY_BASELINE,\n formatBaseline,\n parseBaseline,\n type Baseline,\n type StaleEntry,\n} from './baseline.js';\nimport { discoverConfig, loadConfig, type SpecGraphConfig } from './config.js';\nimport {\n DiffInputError,\n diffExports,\n formatDiffJson,\n formatDiffMarkdown,\n formatDiffText,\n parseGraphExport,\n type GraphExport,\n} from './diff.js';\nimport { isGlob, underRoot } from './glob.js';\nimport { analyse, DEFAULT_PATTERNS, withDiagnostics, type AnalyseOptions, type AnalysisResult } from './runner.js';\nimport {\n formatGitlab,\n formatGraph,\n formatJson,\n formatMarkdown,\n formatReport,\n formatSarif,\n shouldUseAscii,\n shouldUseColor,\n type GraphFormat,\n} from './report.js';\nimport type { ProjectRule } from './project-rules.js';\nimport {\n DEFAULT_SEVERITIES,\n resolveStrict,\n RULE_DECISIONS,\n decisionUrl,\n RULE_DESCRIPTIONS,\n RULE_IDS,\n RULE_QUERIES,\n} from './rules.js';\nimport { isAbsolutePath, toPosix } from './paths.js';\nimport { formatRef } from './source.js';\nimport { execute, parseQuery, QueryError, renderMatch, type Match, type QuerySpec } from './select.js';\nimport { isProjectRule, type AnyRuleId, type RuleId, type Severity, type SpecNode } from './types.js';\n\nexport const EXIT_OK = 0;\nexport const EXIT_FAILED = 1;\nexport const EXIT_ERROR = 2;\n\nexport class UsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UsageError';\n }\n}\n\nexport type Command = 'check' | 'query' | 'graph' | 'rules' | 'diff';\n\nexport interface CliOptions {\n readonly command: Command;\n readonly patterns: readonly string[];\n readonly root: string;\n /**\n * Whether `--root` was given.\n *\n * When it was, the caller has named the root and configuration is read from\n * exactly there. When it was not, the root is discovered - which is a\n * different question from what the root currently is. See ADR-0018.\n */\n readonly rootExplicit: boolean;\n readonly ignore: readonly string[];\n /** Reference targets to leave unreported when they do not resolve. */\n readonly ignoreReferences: readonly string[];\n /** Families a bare identifier may name. Empty means any family in the corpus. */\n readonly families: readonly string[];\n /** Families that are never citations. */\n readonly ignoreFamilies: readonly string[];\n /** Files that log what was decided rather than deciding it. */\n readonly historyPatterns: readonly string[];\n /** Accepted-debt file to read. `null` means none was asked for. */\n readonly baseline: string | null;\n /** Where to write the current findings as accepted debt. */\n readonly recordBaseline: string | null;\n /**\n * Fail when the baseline allows something that no longer happens.\n *\n * The other side of the ratchet, and off by default for the reason ADR-0012\n * gives: failing a build because somebody fixed something is a strange way to\n * encourage them. A team that has decided its debt only goes one way asks for\n * it explicitly, and then a dead exemption cannot outlive the defect.\n */\n readonly ratchet: boolean;\n /** Skip the repository configuration file entirely. */\n readonly noConfig: boolean;\n readonly format: 'human' | 'json' | 'sarif' | 'markdown' | 'gitlab';\n readonly graphFormat: GraphFormat;\n readonly severities: Partial<Record<AnyRuleId, Severity>>;\n readonly color: boolean | null;\n readonly ascii: boolean | null;\n readonly verbose: boolean;\n readonly documentsOnly: boolean;\n readonly max: number;\n readonly maxWarnings: number;\n /** Raise every warning to an error. Explicit `--rule` overrides still win. */\n readonly strict: boolean;\n readonly selector: string | null;\n readonly help: boolean;\n readonly version: boolean;\n}\n\nexport interface CliIO {\n readonly argv?: readonly string[] | undefined;\n readonly cwd?: string | undefined;\n readonly stdout?: ((text: string) => void) | undefined;\n readonly stderr?: ((text: string) => void) | undefined;\n readonly env?: Readonly<Record<string, string | undefined>> | undefined;\n readonly isTTY?: boolean | undefined;\n}\n\nexport const HELP = `spec-graph - turn Markdown specifications into a verifiable graph\n\nUSAGE\n spec-graph [check] [patterns...] [options]\n spec-graph query <selector|project:rule> [patterns...] [options]\n spec-graph graph [patterns...] [--graph-format dot|mermaid|json]\n spec-graph rules [rule-id] [--explain]\n spec-graph diff <before.json> <after.json> [--format human|json|markdown]\n\nCOMMANDS\n check Validate the specification graph. The default.\n query Run a selector - or a registered project rule, by its id - and\n print the matching paths.\n graph Export the graph for Graphviz, Mermaid, or another tool.\n rules List the diagnostics that will run, built in and project. Name one\n to see only that one; --explain adds its selector and the ADR that\n decided it.\n diff Compare two graph exports: documents added, removed, moved or\n accepted; relations added or removed; and obligations resolved or\n reopened where they can be told apart. Make both exports with the\n same spec-graph. Exits 0 whether anything changed or not.\n\nOPTIONS\n --root <dir> Directory the patterns resolve against. Without it,\n .spec-graph.json is looked for in the working\n directory and then upward as far as the repository,\n and the directory holding it becomes the root - so a\n run from a subdirectory reports what a run from the\n top reports. Paths typed on the command line stay\n relative to where they were typed.\n --ignore <glob> Skip paths. Repeatable.\n --ignore-ref <glob> Do not report these reference targets when they fail\n to resolve, for repositories where [[...]] tags a\n concept rather than naming a file. Repeatable.\n Suppresses findings only, never edges.\n --family <name> Families a bare identifier in prose may name. When\n given, everything else stays prose. Repeatable.\n --ignore-family <name> Families that are never citations - RFC when the repo\n cites RFC 2119 and keeps its own RFCs. Repeatable.\n --history <glob> Files that log what was decided rather than deciding\n it - journals, changelogs, minutes. Their links are\n still checked; their obligations are not. Repeatable.\n --baseline <file> Accept the findings recorded in this file and report\n only what is new since. The file has to be there: a\n path that reads nothing accepts nothing and says so\n nowhere. A \"baseline\" in the configuration may name a\n file not recorded yet; a path typed here may not.\n --record-baseline <f> Write today's findings to this file as accepted debt,\n and exit 0 without judging them.\n --ratchet Also fail when a baseline entry no longer occurs, so\n a paid-off exemption cannot outlive the defect.\n --no-config Ignore .spec-graph.json and the package.json key.\n --format <fmt> human, json, sarif, gitlab or markdown. sarif is the\n interchange format GitHub code scanning and editors\n already read, and gitlab the Code Quality report a\n GitLab merge request reads, both for check; markdown\n is a table for a pull-request comment or\n $GITHUB_STEP_SUMMARY, for check or diff\n (default: human)\n --graph-format <fmt> dot, mermaid or json (default: dot)\n --documents-only Leave items out of the exported graph\n --rule <id>=<severity> Override one rule: error, warn, info or off. A project\n rule is named in full: project:no-draft-dependency.\n Repeatable.\n --max <n> Show at most n findings (0 = no limit)\n --max-warnings <n> Fail when warnings exceed n (default: no limit)\n --strict Raise every warning to an error. An explicit --rule\n still wins, so --strict --rule x=warn exempts x.\n --color / --no-color Force colour on or off\n --ascii Use ASCII glyphs only\n --verbose Include parse problems, per-file detail, and every\n reference --ignore-ref or --ignore-family silenced\n -h, --help Show this help\n -v, --version Show the version\n\nSELECTORS\n A selector is a path through the graph.\n\n item[openness=open] -delegates-to-> document[phase=retired]\n document[phase=active] -assumes-> document[phase=retired]\n document =supersedes=> document\n *[path^=docs/adr] -contains-> item[state=accepted-debt]\n\n Node types: document, item, * (any)\n Attributes: id, kind, title, path, file, line, phase, status, receptivity,\n alias, document, state (or disposition), openness, section,\n text, body, evidence, conflicted, fm.<front-matter-key>\n Operators: = != ^= $= *= ~= and [attr] for \"is present\"\n ~= is a regular expression, matched by an automaton that cannot\n backtrack: linear in the subject, whatever the pattern. It reads\n the usual syntax minus backreferences and lookaround, which are\n not regular - both are refused when the selector is read, with\n the character pointed at\n Relations: -kind-> <-kind- =kind=> <=kind= (= forms are transitive)\n\nEXIT CODES\n 0 clean\n 1 findings at error severity (or over --max-warnings)\n 2 the tool could not run\n\nCONFIGURATION\n Anything repeated on every run belongs in the repository rather than in the\n command. spec-graph reads the first of these that exists:\n\n .spec-graph.json, spec-graph.config.json, or a \"spec-graph\" key in\n package.json\n\n { \"patterns\": [\"docs/**/*.md\"],\n \"ignoreReferences\": [\"trap *\"],\n \"ignoreFamilies\": [\"RFC\"],\n \"historyPatterns\": [\"**/JOURNAL_*.md\", \"archive/**\"],\n \"baseline\": \".spec-graph-baseline.json\",\n \"severities\": { \"self-reference\": \"off\" },\n \"strict\": true,\n \"maxRelated\": 3 }\n\n A flag always wins over the file, and list flags add to it rather than\n replacing it. maxRelated has no flag: it caps how many related locations one\n finding lists, 8 unless set, and 0 lists none.\n\n A problem in that file stops the run with exit 2, named on stderr: invalid\n JSON, an unknown key, a rule that does not compile. A configuration that did\n not load checks a different repository than the one configured, and would\n report that one as consistent. --no-config runs on defaults instead.\n\nPROJECT RULES\n A convention spec-graph never anticipated is a selector plus a sentence, and\n belongs in the same file. Every rule declared here runs beside the built-ins\n and is reported, baselined, escalated by --strict and silenced by --rule in\n exactly the same way.\n\n { \"rules\": {\n \"no-draft-dependency\": {\n \"query\": \"document[phase=active] -depends-on-> document[phase=draft]\",\n \"message\": \"{0} depends on {1}, which is still a draft\",\n \"hint\": \"wait for {1} to be accepted, or drop it from {0.path}\",\n \"severity\": \"error\" } } }\n\n query One selector, or a list of them read as a union.\n message The headline. {0} is the first node on the path, {1} the next;\n {1.phase} and {0.fm.owner} read any selector attribute.\n hint The next action. Optional, and templated the same way.\n severity error, warn, info or off. Defaults to warn - a rule a team has\n just written has not yet earned the right to fail their build.\n\n The id is the name with project: in front, which is why it can never collide\n with a built-in. A selector that does not parse, or a {2} the query can never\n reach, is reported when the file is read rather than found missing later.\n\n To see what one matches without copying its selector out of the file:\n\n spec-graph query project:no-draft-dependency --verbose\n\nADOPTING THIS ON AN OLD REPOSITORY\n Record what is already wrong, then report only what happens next:\n\n spec-graph check --record-baseline .spec-graph-baseline.json\n git add .spec-graph-baseline.json\n\n The file is keyed by specification and citation, not by line number, so it\n survives edits, moves and renames. Findings that stop occurring are reported\n so the file can be tightened; nothing new gets in.\n\nEXAMPLES\n spec-graph \"docs/**/*.md\"\n spec-graph check --rule self-reference=off --format json\n spec-graph query 'item[openness=open] -delegates-to-> document[phase=retired]'\n spec-graph check --ignore-ref \"trap *\" # [[trap 55]] tags a concept, not a file\n spec-graph graph --documents-only --graph-format mermaid > graph.mmd\n spec-graph check --history \"**/JOURNAL_*.md\" # a log is not a specification\n spec-graph check --baseline .spec-graph-baseline.json\n spec-graph rules --explain # including this repository's own\n spec-graph rules ghost-handover --explain # and why it exists\n spec-graph check --rule project:no-draft-dependency=off\n spec-graph query project:no-draft-dependency # what does that rule match?\n spec-graph check --format markdown >> \"$GITHUB_STEP_SUMMARY\"\n spec-graph check --format gitlab > gl-code-quality-report.json\n spec-graph diff base.json head.json --format markdown >> \"$GITHUB_STEP_SUMMARY\"\n`;\n\nconst SEVERITIES: readonly Severity[] = ['error', 'warn', 'info', 'off'];\n\n/** Parses argv into options. Throws {@link UsageError} on anything malformed. */\nexport function parseArgs(argv: readonly string[], cwd: string): CliOptions {\n const args = [...argv];\n let command: Command = 'check';\n\n const first = args[0];\n if (first === 'check' || first === 'query' || first === 'graph' || first === 'rules' || first === 'diff') {\n command = first;\n args.shift();\n }\n\n const patterns: string[] = [];\n const ignore: string[] = [];\n const ignoreReferences: string[] = [];\n const families: string[] = [];\n const ignoreFamilies: string[] = [];\n const historyPatterns: string[] = [];\n let noConfig = false;\n const severities: Partial<Record<AnyRuleId, Severity>> = {};\n let root = cwd;\n let rootExplicit = false;\n let format: CliOptions['format'] = 'human';\n let graphFormat: GraphFormat = 'dot';\n let color: boolean | null = null;\n let ascii: boolean | null = null;\n let verbose = false;\n let documentsOnly = false;\n let max = 0;\n let maxWarnings = -1;\n let strict = false;\n let baseline: string | null = null;\n let ratchet = false;\n let recordBaseline: string | null = null;\n let selector: string | null = null;\n let help = false;\n let version = false;\n\n const next = (flag: string, index: number): string => {\n const value = args[index + 1];\n if (value === undefined) throw new UsageError(`${flag} needs a value`);\n return value;\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i] as string;\n\n if (arg === '--') {\n patterns.push(...args.slice(i + 1));\n break;\n }\n\n if (!arg.startsWith('-')) {\n if (command === 'query' && selector === null) selector = arg;\n else patterns.push(arg);\n continue;\n }\n\n switch (arg) {\n case '-h':\n case '--help':\n help = true;\n break;\n case '-v':\n case '--version':\n version = true;\n break;\n case '--verbose':\n verbose = true;\n break;\n case '--color':\n color = true;\n break;\n case '--no-color':\n color = false;\n break;\n case '--ascii':\n ascii = true;\n break;\n case '--documents-only':\n documentsOnly = true;\n break;\n case '--strict':\n strict = true;\n break;\n case '--ratchet':\n ratchet = true;\n break;\n case '--explain':\n verbose = true;\n break;\n case '--root':\n root = next(arg, i);\n rootExplicit = true;\n i += 1;\n break;\n case '--ignore':\n ignore.push(next(arg, i));\n i += 1;\n break;\n case '--ignore-ref':\n ignoreReferences.push(next(arg, i));\n i += 1;\n break;\n case '--family':\n families.push(next(arg, i));\n i += 1;\n break;\n case '--ignore-family':\n ignoreFamilies.push(next(arg, i));\n i += 1;\n break;\n case '--history':\n historyPatterns.push(next(arg, i));\n i += 1;\n break;\n case '--baseline':\n baseline = next(arg, i);\n i += 1;\n break;\n case '--record-baseline':\n recordBaseline = next(arg, i);\n i += 1;\n break;\n case '--no-config':\n noConfig = true;\n break;\n case '--format': {\n const value = next(arg, i);\n if (value !== 'human' && value !== 'json' && value !== 'sarif' && value !== 'markdown' && value !== 'gitlab') {\n throw new UsageError(`--format must be human, json, sarif, markdown or gitlab, got \"${value}\"`);\n }\n format = value;\n i += 1;\n break;\n }\n case '--graph-format': {\n const value = next(arg, i);\n if (value !== 'dot' && value !== 'mermaid' && value !== 'json') {\n throw new UsageError(`--graph-format must be dot, mermaid or json, got \"${value}\"`);\n }\n graphFormat = value;\n i += 1;\n break;\n }\n case '--rule': {\n const value = next(arg, i);\n const equals = value.indexOf('=');\n if (equals === -1) throw new UsageError(`--rule expects <id>=<severity>, got \"${value}\"`);\n const id = value.slice(0, equals) as AnyRuleId;\n const level = value.slice(equals + 1) as Severity;\n // A project rule is taken on its namespace here and checked for real\n // once the configuration defining it has been read: arguments are\n // parsed before any file is opened, and a flag has to be usable on that\n // first pass whatever the repository turns out to declare.\n if (!RULE_IDS.includes(id as RuleId) && !isProjectRule(id)) {\n throw new UsageError(`unknown rule \"${id}\"\\n known rules: ${RULE_IDS.join(', ')}`);\n }\n if (!SEVERITIES.includes(level)) {\n throw new UsageError(`unknown severity \"${level}\", expected one of: ${SEVERITIES.join(', ')}`);\n }\n severities[id] = level;\n i += 1;\n break;\n }\n case '--max': {\n max = parseCount(arg, next(arg, i));\n i += 1;\n break;\n }\n case '--max-warnings': {\n maxWarnings = parseCount(arg, next(arg, i));\n i += 1;\n break;\n }\n default:\n throw new UsageError(`unknown option \"${arg}\"\\n run \"spec-graph --help\" to see the available options`);\n }\n }\n\n // SARIF and GitLab's Code Quality are reports about findings, and only\n // `check` produces those. Falling back to JSON would hand a pipeline something\n // its uploader rejects with a message about a schema rather than about the\n // command that was run. Markdown is for a pull request, which reads a check\n // or a diff.\n if ((format === 'sarif' || format === 'gitlab') && command !== 'check' && !help && !version) {\n throw new UsageError(`--format ${format} reports findings, so it belongs to check, not to ${command}`);\n }\n if (format === 'markdown' && command !== 'check' && command !== 'diff' && !help && !version) {\n throw new UsageError(`--format markdown is a report for a pull request, so it belongs to check or diff, not to ${command}`);\n }\n\n if (command === 'diff' && patterns.length !== 2 && !help && !version) {\n throw new UsageError(\n 'diff compares two graph exports, for example:\\n spec-graph diff base.json head.json\\n (make each with spec-graph graph --graph-format json)',\n );\n }\n\n if (command === 'query' && selector === null && !help && !version) {\n throw new UsageError('query needs a selector, for example:\\n spec-graph query \\'item[openness=open]\\'');\n }\n\n return {\n command,\n patterns,\n root,\n rootExplicit,\n ignore,\n ignoreReferences,\n families,\n ignoreFamilies,\n historyPatterns,\n baseline,\n ratchet,\n recordBaseline,\n noConfig,\n format,\n graphFormat,\n severities,\n color,\n ascii,\n verbose,\n documentsOnly,\n max,\n maxWarnings,\n strict,\n selector,\n help,\n version,\n };\n}\n\nfunction count(n: number, word: string, many?: string): string {\n return `${n} ${n === 1 ? word : (many ?? `${word}s`)}`;\n}\n\ninterface HeldBaseline {\n readonly baseline: Baseline;\n readonly problems: readonly string[];\n /** What stopped the file being read, when something did. */\n readonly unread: { readonly missing: boolean; readonly message: string } | null;\n}\n\n/**\n * Reads a baseline file.\n *\n * Absent and unreadable are different answers, and the caller needs both. A\n * repository that has not recorded a baseline yet declares the path before the\n * file exists, and an empty baseline accepts nothing, which is what that run\n * should report (ADR-0012). Anything else - a directory, a permission, a path\n * that went somewhere unintended - is the tool failing to do what it was told.\n */\nasync function readBaseline(path: string, source: string): Promise<HeldBaseline> {\n let raw: string;\n try {\n const { readFile } = await import('node:fs/promises');\n raw = await readFile(path, 'utf8');\n } catch (error) {\n const failure = error as Error & { code?: string };\n return {\n baseline: EMPTY_BASELINE,\n problems: [],\n unread: { missing: failure.code === 'ENOENT', message: failure.message },\n };\n }\n return { ...parseBaseline(raw, source), unread: null };\n}\n\nfunction parseCount(flag: string, value: string): number {\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || parsed < 0 || String(parsed) !== value.trim()) {\n throw new UsageError(`${flag} expects a non-negative whole number, got \"${value}\"`);\n }\n return parsed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Entry point */\n/* -------------------------------------------------------------------------- */\n\n/** Runs the CLI and returns the process exit code. Never throws. */\nexport async function main(io: CliIO = {}): Promise<number> {\n const argv = io.argv ?? process.argv.slice(2);\n const cwd = io.cwd ?? process.cwd();\n const out = io.stdout ?? ((text) => process.stdout.write(text));\n const err = io.stderr ?? ((text) => process.stderr.write(text));\n const env = io.env ?? process.env;\n\n let options: CliOptions;\n try {\n options = parseArgs(argv, cwd);\n } catch (error) {\n // parseArgs throws nothing but a UsageError for any argv, so no test can\n // tell this check from `true`: the rethrow is for a bug in the parser.\n if (error instanceof UsageError) {\n err(`spec-graph: ${error.message}\\n`);\n return EXIT_ERROR;\n }\n throw error;\n }\n\n if (options.help) {\n out(HELP);\n return EXIT_OK;\n }\n if (options.version) {\n out(`${await readVersion()}\\n`);\n return EXIT_OK;\n }\n\n // A diff reads two files and nothing else: no configuration and no corpus, so\n // it can compare exports from a checkout it is not running in.\n if (options.command === 'diff') return runDiff(options.patterns as readonly [string, string], cwd, options.format, out, err);\n\n const color = options.color ?? shouldUseColor({ isTTY: io.isTTY, env });\n const ascii = options.ascii ?? shouldUseAscii({ env });\n\n // Configuration is what is true of the repository; a flag is somebody\n // overriding it for one run. So a flag always wins, and lists add rather than\n // replace - a `--ignore-ref` on the command line is one more exclusion, not a\n // decision to throw away the ones the repository already declared.\n //\n // Read before `rules` prints anything, so that command lists the conventions\n // this repository will actually check rather than the ones spec-graph ships.\n const loaded = options.noConfig\n ? { config: {} as SpecGraphConfig, source: null, problems: [], root: options.root }\n : options.rootExplicit\n ? { ...loadConfig(options.root), root: options.root }\n : discoverConfig(options.root);\n for (const problem of loaded.problems) err(`spec-graph: ${problem}\\n`);\n // A configuration that did not load means a run against a different\n // repository than the one configured - other patterns, other rules, other\n // severities - and the verdict printed is about that one. Reporting the\n // problem and carrying on gave a green build with `ok: true` from a file with\n // a typo in it, which is the one answer a checker must never reach by\n // accident, and the same mistake in a `--rule` has always exited 2. The\n // findings are one flag away, and the flag is named. Amends ADR-0010.\n if (loaded.problems.length > 0) {\n err(\n `spec-graph: ${count(loaded.problems.length, 'problem')} in the configuration, so nothing was checked\\n fix it, or run again with --no-config to check on defaults\\n`,\n );\n return EXIT_ERROR;\n }\n const file = loaded.config;\n const projectRules = file.rules ?? [];\n const root = loaded.root;\n // How far the root moved up. Everything a repository declares about itself is\n // relative to the root; everything typed on the command line is relative to\n // where it was typed, and this is what keeps those two readings apart.\n const here = below(root, options.root);\n\n // A `--rule` naming a project rule that does not exist is a flag that\n // silently does nothing, and nothing in the output would distinguish that\n // from a rule that ran and found none.\n for (const id of Object.keys(options.severities)) {\n if (!isProjectRule(id as AnyRuleId) || projectRules.some((rule) => rule.id === id)) continue;\n err(`spec-graph: unknown rule \"${id}\"\\n ${knownProjectRules(projectRules)}\\n`);\n return EXIT_ERROR;\n }\n\n if (options.command === 'rules') {\n // The one positional argument `rules` can take is a rule id: this command\n // reads no files, so a pattern here would be a word with nowhere to go.\n const wanted = options.patterns[0];\n if (wanted !== undefined && !RULE_IDS.includes(wanted as RuleId) && !projectRules.some((rule) => rule.id === wanted)) {\n err(\n `spec-graph: unknown rule \"${wanted}\"\\n known rules: ${RULE_IDS.join(', ')}\\n ${knownProjectRules(projectRules)}\\n`,\n );\n return EXIT_ERROR;\n }\n out(renderRules(options.verbose, await readVersion(), projectRules, wanted ?? null, loaded.source));\n return EXIT_OK;\n }\n\n const patterns =\n options.patterns.length > 0 ? options.patterns.map((pattern) => anchor(here, pattern)) : (file.patterns ?? DEFAULT_PATTERNS);\n const severityOverrides = { ...(file.severities ?? {}), ...options.severities };\n const { severities, escalated } = resolveStrict(\n severityOverrides,\n options.strict || (file.strict ?? false),\n projectRules,\n );\n\n const analyseOptions: AnalyseOptions = {\n root,\n patterns,\n // A bare name prunes a directory of that name at any depth, the way a\n // .gitignore line does, so it means the same thing wherever it was typed.\n // A path or a glob is matched against the repository-relative path, and\n // leaving that one alone would make it silently match nothing.\n //\n // A stray entry in one of the empty fallbacks below changes a run only if\n // it matches a path, a target or a family some corpus has, so the mutants\n // that plant one survive every corpus but one built for them - except in\n // `families`, where any entry is an allowlist.\n ignore: [...(file.ignore ?? []), ...options.ignore.map((pattern) => anchorPath(here, pattern))],\n ignoreReferences: [...(file.ignoreReferences ?? []), ...options.ignoreReferences],\n families: [...(file.families ?? []), ...options.families],\n ignoreFamilies: [...(file.ignoreFamilies ?? []), ...options.ignoreFamilies],\n historyPatterns: [...(file.historyPatterns ?? []), ...options.historyPatterns.map((pattern) => anchorPath(here, pattern))],\n severities,\n projectRules,\n maxRelated: file.maxRelated,\n };\n\n // Named the way the reader would have to type it, because a discovered\n // configuration is often not the one in front of them.\n //\n // On stderr, with everything else this run says about itself. stdout is the\n // report, and in three of the four formats it is a document: a line above it\n // made `--verbose --format json` unparseable and handed `--format sarif` to a\n // code-scanning uploader that rejects it over a schema.\n if (options.verbose && loaded.source !== null) {\n const depth = here === '' ? 0 : here.split('/').length;\n err(`configuration: ${'../'.repeat(depth)}${loaded.source}\\n`);\n }\n\n let result;\n try {\n result = await analyse(analyseOptions);\n } catch (error) {\n err(`spec-graph: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n\n if (result.files.length === 0) {\n err(\n `spec-graph: no specifications matched ${\n patterns.map((p) => `\"${p}\"`).join(', ')\n }\\n looked under ${root}\\n`,\n );\n return EXIT_ERROR;\n }\n\n switch (options.command) {\n case 'graph':\n out(\n formatGraph(result.graph, options.graphFormat, {\n documentsOnly: options.documentsOnly,\n generator: { name: 'spec-graph', version: await readVersion() },\n }),\n );\n return EXIT_OK;\n\n case 'query': {\n const selector = options.selector as string;\n let queries: readonly QuerySpec[];\n\n // A registered rule is asked for by name, because by the time this runs\n // it is already compiled and the alternative is copying its selector out\n // of the configuration file by hand. The namespace cannot collide with\n // the grammar: no selector begins with a word and a colon. See ADR-0016.\n if (isProjectRule(selector as AnyRuleId)) {\n const rule = projectRules.find((candidate) => candidate.id === selector);\n if (rule === undefined) {\n err(`spec-graph: unknown rule \"${selector}\"\\n ${knownProjectRules(projectRules)}\\n`);\n return EXIT_ERROR;\n }\n queries = rule.queries;\n // Beside the report rather than inside it, for the reason the\n // configuration line above is: `--format json` is a document.\n if (options.verbose) for (const source of rule.sources) err(`${rule.id}: ${source}\\n`);\n } else {\n try {\n queries = [parseQuery(selector)];\n } catch (error) {\n // Every selector that fails to parse fails as a QueryError, so no\n // test can tell this check from `true`.\n if (error instanceof QueryError) {\n err(renderQueryError(selector, error));\n return EXIT_ERROR;\n }\n throw error;\n }\n }\n\n const matches = union(result.graph, queries);\n // renderMatches asks only whether this is 'json', so the other word is a\n // name for the reader and emptying it changes nothing.\n out(renderMatches(matches, options.format === 'json' ? 'json' : 'human', result.graph.nodes.size));\n return matches.length > 0 ? EXIT_OK : EXIT_FAILED;\n }\n\n default: {\n // Recording is not checking. It writes down what is wrong today so that\n // tomorrow can be compared against it, and says nothing about whether\n // today is acceptable - so it reports what it wrote and exits clean.\n if (options.recordBaseline !== null) {\n const text = formatBaseline(result.graph, result.diagnostics);\n try {\n const { writeFile } = await import('node:fs/promises');\n // Node writes a string as UTF-8 when the encoding is empty too, so\n // emptying this literal writes the same bytes.\n await writeFile(underRoot(root, anchor(here, options.recordBaseline)), text, 'utf8');\n } catch (error) {\n err(`spec-graph: cannot write ${options.recordBaseline}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n const entries = (JSON.parse(text) as Baseline).findings.length;\n out(\n `recorded ${count(result.diagnostics.length, 'finding')} as ${count(entries, 'entry', 'entries')} in ${options.recordBaseline}\\n`,\n );\n return EXIT_OK;\n }\n\n const source = options.baseline === null ? (file.baseline ?? null) : anchor(here, options.baseline);\n const ratchet = options.ratchet || file.ratchet === true;\n let reported = result;\n let note:\n | {\n source: string;\n suppressed: number;\n stale: number;\n ratchet: boolean;\n entries: readonly StaleEntry[];\n }\n | undefined;\n if (source !== null) {\n const held = await readBaseline(underRoot(root, source), source);\n // A path typed on the command line says the file is there for this run.\n // Read as an empty baseline instead, a typo in it reports every accepted\n // finding as new, and passes --ratchet with nothing left to be stale.\n // A path in the configuration is the case ADR-0012 argued for, and only\n // where the file is absent: unreadable is unreadable wherever the path\n // was written.\n if (held.unread !== null && (options.baseline !== null || !held.unread.missing)) {\n err(`spec-graph: cannot read the baseline ${source}: ${held.unread.message}\\n`);\n return EXIT_ERROR;\n }\n // Quiet by default, because a configured path legitimately precedes the\n // first --record-baseline. Under --verbose, where parse problems already\n // go, a path that reads nothing says so rather than accepting nothing.\n if (held.unread !== null && options.verbose) {\n err(`spec-graph: baseline ${source} is not there, so nothing is accepted\\n`);\n }\n for (const problem of held.problems) err(`spec-graph: ${problem}\\n`);\n const outcome = applyBaseline(result.graph, result.diagnostics, held.baseline);\n reported = withDiagnostics(result, outcome.kept);\n note = {\n source,\n suppressed: outcome.suppressed,\n stale: outcome.stale.length,\n ratchet,\n entries: outcome.stale,\n };\n // Listed rather than counted when the run turns on them: a number is\n // enough to know the file has slack, and not enough to strike it. On\n // stdout only for a human - the structured formats carry the same rows\n // inside the document, where a stray line is the difference between\n // parsing and not.\n if (options.format === 'human' && (options.verbose || ratchet)) {\n for (const entry of outcome.stale) {\n const subject = entry.subject === '' ? '' : ` \"${entry.subject}\"`;\n const why = entry.reason === 'gone' ? ` - ${entry.document} is not in this corpus` : '';\n out(` ${entry.reason}: ${entry.rule} ${entry.document}${subject}${why}\\n`);\n }\n }\n }\n const looseBaseline = note !== undefined && note.ratchet && note.stale > 0;\n\n const reporterOptions = { verbose: options.verbose, max: options.max, escalated, baseline: note };\n out(\n options.format === 'sarif'\n ? formatSarif(reported, reported.graph, { version: await readVersion(), escalated, projectRules })\n : options.format === 'gitlab'\n ? formatGitlab(reported, { escalated })\n : options.format === 'json'\n ? formatJson(reported, { escalated, baseline: note })\n : options.format === 'markdown'\n ? formatMarkdown(reported, reporterOptions)\n : `${formatReport(reported, { color, ascii, ...reporterOptions })}\\n`,\n );\n if (!reported.ok || looseBaseline) return EXIT_FAILED;\n if (options.maxWarnings >= 0 && reported.summary.warnings > options.maxWarnings) return EXIT_FAILED;\n return EXIT_OK;\n }\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Rendering */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Where the working directory sits below the root, or `''` when it is the root.\n *\n * Discovery only ever walks upward, so the root is always a prefix of the\n * directory the command was typed in, and this is a slice rather than path\n * arithmetic.\n */\nfunction below(root: string, from: string): string {\n const start = toPosix(from).replace(/[/]+$/, '');\n // The prefix test only guards a root that is neither `start` nor above it,\n // which nothing returns; for `start` itself, slicing past its end is `''`\n // too, so emptying the prefix changes nothing a run can reach.\n return start.startsWith(`${root}/`) ? start.slice(root.length + 1) : '';\n}\n\n/**\n * Re-anchors a path typed in `prefix` so it reads from the root.\n *\n * An absolute path is left alone: it was not relative to anywhere, so moving\n * the root cannot change what it means.\n */\nfunction anchor(prefix: string, value: string): string {\n if (prefix === '' || isAbsolutePath(value)) return value;\n const negated = value.startsWith('!');\n const directories = prefix.split('/');\n let rest = toPosix(negated ? value.slice(1) : value);\n // `../docs` typed one directory down is the root's `docs`. That is arithmetic\n // on two relative paths, and this is the one place both are known; left in\n // the pattern, it reads as a glob climbing out of the root, which is refused.\n // A bare `..` typed in `docs/deep` leaves `docs/`: the directory's contents,\n // which is what it named.\n while (directories.length > 0 && (rest === '..' || rest.startsWith('../'))) {\n directories.pop();\n rest = rest.slice(3);\n }\n const joined = [...directories, rest].join('/');\n return negated ? `!${joined}` : joined;\n}\n\n/** The same, for an ignore, where a bare name is a directory at any depth. */\nfunction anchorPath(prefix: string, pattern: string): string {\n return isGlob(pattern) || pattern.includes('/') ? anchor(prefix, pattern) : pattern;\n}\n\nfunction knownProjectRules(projectRules: readonly ProjectRule[]): string {\n const known = projectRules.map((rule) => rule.id);\n return known.length > 0 ? `project rules here: ${known.join(', ')}` : 'this repository defines no project rules';\n}\n\n/**\n * Runs a list of selectors as one result set.\n *\n * A project rule is a union of its selectors, and a path that two of them both\n * find is one path - the same dedupe `projectFindings` does, so that asking\n * this command what a rule matches answers with the set `check` reports on.\n */\nfunction union(graph: AnalysisResult['graph'], queries: readonly QuerySpec[]): Match[] {\n // `execute` already returns each path of nodes once, keyed the way this is,\n // so one selector needs no second pass and sending it through one anyway\n // returns the same matches.\n if (queries.length === 1) return execute(graph, queries[0] as QuerySpec);\n const seen = new Set<string>();\n const matches: Match[] = [];\n for (const spec of queries) {\n for (const match of execute(graph, spec)) {\n const key = match.nodes.map((node) => node.id).join('>');\n if (seen.has(key)) continue;\n seen.add(key);\n matches.push(match);\n }\n }\n return matches;\n}\n\ninterface RuleRow {\n readonly id: string;\n readonly severity: Severity;\n readonly description: string;\n /** The selector, where the rule is one. */\n readonly query: string | undefined;\n /** Where the reasoning is: an ADR, or the file that declared the rule. */\n readonly decided: string;\n}\n\nfunction renderRules(\n explain: boolean,\n version: string,\n projectRules: readonly ProjectRule[],\n only: string | null,\n configSource: string | null,\n): string {\n // A project rule is described by the selector it is, because that is what it\n // is - its message is a template, and a template is not a description.\n const rows: RuleRow[] = [\n ...RULE_IDS.map((id): RuleRow => ({\n id,\n severity: DEFAULT_SEVERITIES[id],\n description: RULE_DESCRIPTIONS[id],\n query: RULE_QUERIES[id],\n decided: decisionUrl(RULE_DECISIONS[id], version),\n })),\n ...projectRules.map((rule): RuleRow => ({\n id: rule.id,\n severity: rule.severity,\n description: rule.sources[0] as string,\n query: rule.sources.slice(1).join(' | ') || undefined,\n // A project rule only exists because a file declared it, so the source\n // is never null here and the first branch is for the type alone.\n decided: configSource === null ? `rules.${rule.name}` : `${configSource}: rules.${rule.name}`,\n })),\n ];\n\n const shown = only === null ? rows : rows.filter((row) => row.id === only);\n const width = Math.max(...shown.map((row) => row.id.length));\n const lines: string[] = [];\n for (const row of shown) {\n lines.push(`${row.id.padEnd(width)} ${row.severity.padEnd(5)} ${row.description}`);\n if (!explain) continue;\n if (row.query) lines.push(`${' '.repeat(width)} ${row.query}`);\n // Where the decision is written down, rather than a second copy of it. A\n // reader who has just been told their document is inconsistent is entitled\n // to know who decided that and why, and the ADR is the answer.\n lines.push(`${' '.repeat(width)} ${row.decided}`);\n }\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction renderMatches(matches: readonly Match[], format: 'human' | 'json', total: number): string {\n if (format === 'json') {\n return `${JSON.stringify(\n {\n version: 1,\n count: matches.length,\n matches: matches.map((match) => ({\n nodes: match.nodes.map((node) => nodeSummary(node)),\n edges: match.edges.map((edge) => ({\n kind: edge.kind,\n from: edge.from,\n to: edge.to,\n file: edge.declaredAt.file,\n line: edge.declaredAt.span.start.line,\n })),\n })),\n },\n null,\n 2,\n )}\\n`;\n }\n\n if (matches.length === 0) return `no matches (searched ${total} nodes)\\n`;\n\n const lines: string[] = [];\n for (const match of matches) {\n const head = match.nodes[0] as SpecNode;\n const tail = match.nodes[match.nodes.length - 1] as SpecNode;\n lines.push(renderMatch(match));\n lines.push(` ${formatRef(head.at)}${match.nodes.length > 1 ? ` ${formatRef(tail.at)}` : ''}`);\n }\n lines.push(`${matches.length} ${matches.length === 1 ? 'match' : 'matches'}`);\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction nodeSummary(node: SpecNode): Record<string, unknown> {\n return {\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 ...(node.kind === 'document' ? { phase: node.phase } : { state: node.disposition, openness: node.openness }),\n };\n}\n\n/** Points at the exact character of a selector that failed to parse. */\nfunction renderQueryError(selector: string, error: QueryError): string {\n const caret = `${' '.repeat(Math.max(0, error.offset))}^`;\n return `spec-graph: ${error.message}\\n ${selector}\\n ${caret}\\n`;\n}\n\n/**\n * Compares two exports.\n *\n * Exit 0 whether anything changed or not: a diff describes, and `check` gates. A\n * diff that failed on a removed relation would fail every legitimate\n * supersession (ADR-0020).\n */\nasync function runDiff(\n paths: readonly [string, string],\n cwd: string,\n format: CliOptions['format'],\n out: (text: string) => void,\n err: (text: string) => void,\n): Promise<number> {\n const { readFile } = await import('node:fs/promises');\n const { resolve } = await import('node:path');\n const sides: GraphExport[] = [];\n for (const path of paths) {\n let raw: string;\n try {\n // Without the encoding this is a Buffer, which JSON.parse decodes as\n // UTF-8 all the same - so emptying the literal parses the same export.\n raw = await readFile(resolve(cwd, path), 'utf8');\n } catch (error) {\n err(`spec-graph: cannot read ${path}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n try {\n sides.push(parseGraphExport(raw, path));\n } catch (error) {\n // Every input parseGraphExport refuses, it refuses as a DiffInputError;\n // the rethrow is for a bug in it, which no file reaches.\n if (!(error instanceof DiffInputError)) throw error;\n err(`spec-graph: ${error.message}\\n`);\n return EXIT_ERROR;\n }\n }\n const [before, after] = sides as [GraphExport, GraphExport];\n const diff = diffExports(before, after);\n out(format === 'json' ? formatDiffJson(diff) : format === 'markdown' ? formatDiffMarkdown(diff) : formatDiffText(diff));\n return EXIT_OK;\n}\n\n/**\n * The version in the package's own manifest.\n *\n * The guards and the placeholder are for a manifest that is missing or\n * malformed, and the one this reads always parses and always has a version, so\n * no test reaches them without replacing the file the package ships - and the\n * same parse without the encoding reads a Buffer, which JSON.parse decodes as\n * UTF-8 all the same.\n */\nasync function readVersion(): Promise<string> {\n try {\n const { readFile } = await import('node:fs/promises');\n const url = new URL('../package.json', import.meta.url);\n const parsed: unknown = JSON.parse(await readFile(url, 'utf8'));\n if (typeof parsed === 'object' && parsed !== null && 'version' in parsed) {\n return String((parsed as { version: unknown }).version);\n }\n } catch {\n // Fall through to the placeholder rather than failing `--version`.\n }\n return '0.0.0';\n}\n"]}
package/dist/config.d.ts CHANGED
@@ -12,9 +12,9 @@
12
12
  * and a YAML or TOML reader would be the largest thing in the package, to read
13
13
  * a file with nine keys in it.
14
14
  *
15
- * Every key mirrors a flag, and a flag always wins. Configuration is where a
16
- * team writes down what is true of the repository; a flag is where somebody
17
- * overrides it for one run.
15
+ * Every key but `rules` and `maxRelated` mirrors a flag, and a flag always
16
+ * wins. Configuration is where a team writes down what is true of the
17
+ * repository; a flag is where somebody overrides it for one run.
18
18
  */
19
19
  import { type ProjectRule } from './project-rules.js';
20
20
  import { type AnyRuleId, type Severity } from './types.js';