@descent-vtt/spec-guard 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * The layering rule behind `@assert-layers`.
3
+ *
4
+ * Pure, and built on almost nothing new. A layer is a pattern in the language
5
+ * `module=` and `exclude` already speak; a file belongs to a layer when its path
6
+ * matches, and a reference points into one when any name it can denote does -
7
+ * see `referenceForms`. That is why layering needs no resolver and works in
8
+ * every language spec-guard reads: it never asks which file a reference *is*,
9
+ * only which areas it could be about.
10
+ *
11
+ * Cycles are the opposite case, and live in `graph.ts` - see ADR-0011.
12
+ */
13
+ import { type ModuleReference } from './imports.js';
14
+ /**
15
+ * Every name a reference can be matched under.
16
+ *
17
+ * The specifier as written and the module it resolves to, as `module=` tries -
18
+ * and, for the two languages whose modules are files, the files that module can
19
+ * denote. Without the last, a layer that names a file could never be reached:
20
+ * `src/runner.ts` is where the file is, `./runner.js` is what imports it, and
21
+ * the first rule this project wrote with file-sized layers passed while its
22
+ * order was reversed, because no reference matched any layer at all.
23
+ *
24
+ * Names only. Nothing here asks whether a candidate exists, which is why a layer
25
+ * outside the assertion's target still works: `../infrastructure/db.js` reaches
26
+ * `src/infrastructure/db.ts` whether or not the walk ever went there.
27
+ */
28
+ export declare function referenceForms(specifier: string, importingFile: string): string[];
29
+ export interface LayerInput {
30
+ /** Root-relative path of the importing file. */
31
+ file: string;
32
+ references: readonly ModuleReference[];
33
+ }
34
+ export interface LayerViolation {
35
+ file: string;
36
+ /** The layer the file belongs to, as an index into the order. */
37
+ from: number;
38
+ /** The latest layer its reference reaches, also an index. */
39
+ to: number;
40
+ /** The first reference, in source order, that reaches a later layer. */
41
+ reference: ModuleReference;
42
+ }
43
+ export interface LayerReport {
44
+ /** Files in scope matched by each layer, by index. */
45
+ members: number[];
46
+ /** Files in scope that no layer matches, and which are therefore unconstrained. */
47
+ unassigned: string[];
48
+ /** Files matched by more than one layer, with every layer that matched. */
49
+ ambiguous: Array<{
50
+ file: string;
51
+ layers: number[];
52
+ }>;
53
+ /** At most one per file. */
54
+ violations: LayerViolation[];
55
+ }
56
+ /** A function from a path to the indices of every layer that matches it. */
57
+ export declare function layerMatcher(order: readonly string[]): (relativePath: string) => number[];
58
+ /**
59
+ * Checks each file's references against the order.
60
+ *
61
+ * A file may import from its own layer and from layers listed before it. The
62
+ * unit of violation is the file, as it is for every import assertion: one
63
+ * import statement split into two is not twice the problem.
64
+ *
65
+ * A file two layers claim is not checked for violations - which layer's rule
66
+ * applies is exactly the thing that is unknown - and is reported instead. So is
67
+ * every file no layer claims, because a shared utility and a directory someone
68
+ * forgot to assign look identical from here and only the author can say which a
69
+ * count describes.
70
+ */
71
+ export declare function checkLayers(inputs: readonly LayerInput[], order: readonly string[], includeTypes: boolean): LayerReport;
72
+ //# sourceMappingURL=layers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../src/layers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAGnE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAKjF;AAED,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mFAAmF;IACnF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2EAA2E;IAC3E,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACrD,4BAA4B;IAC5B,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,EAAE,CAIzF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,OAAO,GAAG,WAAW,CA6CvH"}
package/dist/layers.js ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * The layering rule behind `@assert-layers`.
3
+ *
4
+ * Pure, and built on almost nothing new. A layer is a pattern in the language
5
+ * `module=` and `exclude` already speak; a file belongs to a layer when its path
6
+ * matches, and a reference points into one when any name it can denote does -
7
+ * see `referenceForms`. That is why layering needs no resolver and works in
8
+ * every language spec-guard reads: it never asks which file a reference *is*,
9
+ * only which areas it could be about.
10
+ *
11
+ * Cycles are the opposite case, and live in `graph.ts` - see ADR-0011.
12
+ */
13
+ import { createExcludeMatcher } from './glob.js';
14
+ import { candidates, isGraphFile } from './graph.js';
15
+ import { resolveModule } from './imports.js';
16
+ import { languageFor } from './polyglot.js';
17
+ /**
18
+ * Every name a reference can be matched under.
19
+ *
20
+ * The specifier as written and the module it resolves to, as `module=` tries -
21
+ * and, for the two languages whose modules are files, the files that module can
22
+ * denote. Without the last, a layer that names a file could never be reached:
23
+ * `src/runner.ts` is where the file is, `./runner.js` is what imports it, and
24
+ * the first rule this project wrote with file-sized layers passed while its
25
+ * order was reversed, because no reference matched any layer at all.
26
+ *
27
+ * Names only. Nothing here asks whether a candidate exists, which is why a layer
28
+ * outside the assertion's target still works: `../infrastructure/db.js` reaches
29
+ * `src/infrastructure/db.ts` whether or not the walk ever went there.
30
+ */
31
+ export function referenceForms(specifier, importingFile) {
32
+ const module = resolveModule(specifier, importingFile);
33
+ if (isGraphFile(importingFile))
34
+ return [specifier, ...candidates(module)];
35
+ if (languageFor(importingFile) === 'python')
36
+ return [specifier, module, `${module}.py`, `${module}/__init__.py`];
37
+ return [specifier, module];
38
+ }
39
+ /** A function from a path to the indices of every layer that matches it. */
40
+ export function layerMatcher(order) {
41
+ const matchers = order.map((pattern) => createExcludeMatcher([pattern]));
42
+ return (relativePath) => matchers.flatMap((matches, layer) => (matches(relativePath) ? [layer] : []));
43
+ }
44
+ /**
45
+ * Checks each file's references against the order.
46
+ *
47
+ * A file may import from its own layer and from layers listed before it. The
48
+ * unit of violation is the file, as it is for every import assertion: one
49
+ * import statement split into two is not twice the problem.
50
+ *
51
+ * A file two layers claim is not checked for violations - which layer's rule
52
+ * applies is exactly the thing that is unknown - and is reported instead. So is
53
+ * every file no layer claims, because a shared utility and a directory someone
54
+ * forgot to assign look identical from here and only the author can say which a
55
+ * count describes.
56
+ */
57
+ export function checkLayers(inputs, order, includeTypes) {
58
+ const layersOf = layerMatcher(order);
59
+ // Every file in a directory imports the same few modules, and each reference
60
+ // is matched under some twenty names, so the same name is matched against the
61
+ // same patterns thousands of times on a large tree. The answer depends on the
62
+ // name alone. Measured on 6,977 files of node_modules: see ADR-0011.
63
+ const seen = new Map();
64
+ const reachedBy = (name) => {
65
+ let layers = seen.get(name);
66
+ if (layers === undefined) {
67
+ layers = layersOf(name);
68
+ seen.set(name, layers);
69
+ }
70
+ return layers;
71
+ };
72
+ const members = order.map(() => 0);
73
+ const unassigned = [];
74
+ const ambiguous = [];
75
+ const violations = [];
76
+ for (const { file, references } of inputs) {
77
+ const own = layersOf(file);
78
+ for (const layer of own)
79
+ members[layer] = members[layer] + 1;
80
+ if (own.length === 0) {
81
+ unassigned.push(file);
82
+ continue;
83
+ }
84
+ if (own.length > 1) {
85
+ ambiguous.push({ file, layers: own });
86
+ continue;
87
+ }
88
+ const from = own[0];
89
+ for (const reference of references) {
90
+ if (reference.typeOnly && !includeTypes)
91
+ continue;
92
+ const reached = referenceForms(reference.specifier, file).flatMap(reachedBy);
93
+ const to = Math.max(from, ...reached);
94
+ if (to > from) {
95
+ violations.push({ file, from, to, reference });
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ return { members, unassigned, ambiguous, violations };
101
+ }
102
+ //# sourceMappingURL=layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layers.js","sourceRoot":"","sources":["../src/layers.ts"],"names":[],"mappings":"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"}
package/dist/parser.d.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * error rather than silently skipped - a typo must never turn into a
15
15
  * silently-passing invariant.
16
16
  */
17
- import type { DirectiveKind, ParseResult } from './types.js';
17
+ import type { DirectiveKind, ParseResult, SpecStatus } from './types.js';
18
18
  /** Every directive spec-guard understands. */
19
19
  export declare const KINDS: Set<string>;
20
20
  /**
@@ -26,6 +26,30 @@ export declare const KINDS: Set<string>;
26
26
  * from any kind and nothing would have said so.
27
27
  */
28
28
  export declare const ALLOWED_ATTRIBUTES: Record<DirectiveKind, ReadonlySet<string>>;
29
+ /**
30
+ * Status words that withhold a document's directives from execution.
31
+ *
32
+ * The words that mean "not in force" in Nygard's ADR template and in MADR's
33
+ * between them, plus `draft`, which is the one people actually type. The list
34
+ * is closed and short on purpose: every word added to it is another way for a
35
+ * document to go dark, and a rule that stops being enforced without anyone
36
+ * deciding so is the failure this tool exists to prevent. Anything else - an
37
+ * unrecognised word, a misspelling, no status at all - stays in force. See
38
+ * ADR-0010.
39
+ */
40
+ export declare const INACTIVE_STATUSES: ReadonlySet<string>;
41
+ /**
42
+ * The lifecycle status a Markdown document declares about itself.
43
+ *
44
+ * Three spellings are recognised because three are in use, including two in
45
+ * this repository's own ADRs: YAML front-matter (MADR), a `## Status` section
46
+ * (Nygard), and a bold `**Status:**` label. Front-matter wins when present -
47
+ * it is machine-readable metadata rather than a convention read out of prose.
48
+ *
49
+ * Code is masked first, so a document that documents this syntax inside a
50
+ * fence - this project's README does - is not read as declaring a status.
51
+ */
52
+ export declare function parseStatus(source: string): SpecStatus | undefined;
29
53
  export interface ParseContext {
30
54
  /** Absolute path of the spec file. */
31
55
  file: string;
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAA6B,aAAa,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAExG,8CAA8C;AAC9C,eAAO,MAAM,KAAK,aAMhB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAwDzE,CAAC;AAMF,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAwD/C;AAMD,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUrE;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAkDlF"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAGV,aAAa,EACb,WAAW,EAEX,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,8CAA8C;AAC9C,eAAO,MAAM,KAAK,aAQhB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAuEzE,CAAC;AAIF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAMhD,CAAC;AA+HH;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAElE;AAWD,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAwD/C;AAMD,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUrE;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAmDlF"}
package/dist/parser.js CHANGED
@@ -22,6 +22,8 @@ export const KINDS = new Set([
22
22
  'assert-present',
23
23
  'assert-import-absence',
24
24
  'assert-import-count',
25
+ 'assert-import-cycle',
26
+ 'assert-layers',
25
27
  ]);
26
28
  /**
27
29
  * Which attributes each directive accepts.
@@ -87,7 +89,181 @@ export const ALLOWED_ATTRIBUTES = {
87
89
  'allow-empty',
88
90
  'reason',
89
91
  ]),
92
+ // No baseline: a baseline lists files, and a cycle is not a file. Exempting
93
+ // the files of today's cycle would exempt a new one among the same files.
94
+ 'assert-import-cycle': new Set(['target', 'exclude', 'types', 'expected', 'max', 'allow-empty', 'reason']),
95
+ 'assert-layers': new Set([
96
+ 'target',
97
+ 'order',
98
+ 'exclude',
99
+ 'types',
100
+ 'expected',
101
+ 'max',
102
+ 'allow-empty',
103
+ 'baseline',
104
+ 'ratchet',
105
+ 'reason',
106
+ ]),
90
107
  };
108
+ /* --------------------------------------------------------------- the status */
109
+ /**
110
+ * Status words that withhold a document's directives from execution.
111
+ *
112
+ * The words that mean "not in force" in Nygard's ADR template and in MADR's
113
+ * between them, plus `draft`, which is the one people actually type. The list
114
+ * is closed and short on purpose: every word added to it is another way for a
115
+ * document to go dark, and a rule that stops being enforced without anyone
116
+ * deciding so is the failure this tool exists to prevent. Anything else - an
117
+ * unrecognised word, a misspelling, no status at all - stays in force. See
118
+ * ADR-0010.
119
+ */
120
+ export const INACTIVE_STATUSES = new Set([
121
+ 'draft',
122
+ 'proposed',
123
+ 'rejected',
124
+ 'deprecated',
125
+ 'superseded',
126
+ ]);
127
+ /** `---\n...\n---` at the very top of the file, and nowhere else. */
128
+ const FRONTMATTER_RE = /^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/;
129
+ /**
130
+ * The three ways the key is spelled: `**Status**:`, `**Status:**`, `Status:`.
131
+ *
132
+ * Written as alternatives rather than as optional emphasis on either side of
133
+ * the colon, which is what it used to be - and an optional `**` after the colon
134
+ * cannot tell the key's closing marker from the value's opening one, so
135
+ * `Status: **Draft**` reached the report as "Draft**". Here emphasis after the
136
+ * colon is only consumed when it closes emphasis that opened the key. The
137
+ * colon itself is mandatory, which keeps "Status reports are..." from being
138
+ * read as metadata. Leading whitespace in the value is left to `toStatus`,
139
+ * which trims it anyway.
140
+ */
141
+ const STATUS_LABEL_RE = /^[ \t]{0,3}(?:(\*\*|__)status(?:\1[ \t]*:|[ \t]*:\1)|status[ \t]*:)(.*)/i;
142
+ /**
143
+ * The value a YAML scalar holds: a quoted one up to its closing quote, a plain
144
+ * one up to a comment.
145
+ *
146
+ * Not a YAML parser, and it does not need to be one - it reads one line. But
147
+ * it has to read that line the way YAML does. MADR's own template quotes the
148
+ * status, and a quote left in leaves no first word to read; a trailing
149
+ * `# decided at review` left in is part of the label; and a regex anchored at
150
+ * both ends of a quoted value read `"proposed" # a comment` as no status at
151
+ * all, which keeps a withdrawn proposal in force.
152
+ */
153
+ function yamlScalar(raw) {
154
+ const text = raw.trim();
155
+ const quoted = /^(["'])(.*?)\1/.exec(text);
156
+ return quoted ? quoted[2] : text.replace(/\s#.*/, '');
157
+ }
158
+ /** An ATX heading whose entire text is "Status". */
159
+ const STATUS_HEADING_RE = /^[ \t]{0,3}#{1,6}[ \t]+status[ \t]*#*[ \t]*$/i;
160
+ /** Any ATX heading of level 2 or deeper - where a document's preamble ends. */
161
+ const SECTION_HEADING_RE = /^[ \t]{0,3}#{2,6}[ \t]/;
162
+ /**
163
+ * Turns a status line into a status, or into nothing.
164
+ *
165
+ * The value is the first run of letters, so "Accepted (0.3.0)." and
166
+ * "Superseded by ADR-0007" normalise to one word while the line as written
167
+ * survives for the report - a reader shown "superseded" learns much less than
168
+ * one shown what it was superseded by.
169
+ */
170
+ function toStatus(raw, source) {
171
+ const trimmed = raw.trim();
172
+ // The word is read through any leading emphasis, so `**Superseded** by
173
+ // ADR-0007` is superseded rather than nothing at all - which is what a rule
174
+ // that required the markers to balance made of it.
175
+ const word = /^[*_]*([a-zA-Z]+)/.exec(trimmed);
176
+ if (!word)
177
+ return undefined;
178
+ // The label loses emphasis only when it wraps the whole line. `**Draft**` is
179
+ // a status written in bold and reads better without the markers; "Superseded
180
+ // by *ADR-0007*" is a sentence with emphasis inside it, and taking one marker
181
+ // off each end would put a half-mangled line in the report.
182
+ const label = trimmed.replace(/^(\*{1,2}|_{1,2})(.*)\1$/, '$2');
183
+ const value = word[1].toLowerCase();
184
+ return { value, label, source, active: !INACTIVE_STATUSES.has(value) };
185
+ }
186
+ /**
187
+ * Lines, whichever way the file ends them.
188
+ *
189
+ * Splitting on "\n" alone leaves a carriage return on every line of a CRLF
190
+ * document, and a trailing "\r" defeats every `$` below - so a Windows-checkout
191
+ * ADR declared no status at all, silently, which is the one failure mode this
192
+ * feature must not have. Found by running the parser over this repository's own
193
+ * ADR-0003, which happened to be CRLF on disk.
194
+ */
195
+ function toLines(masked) {
196
+ return masked.split(/\r?\n/);
197
+ }
198
+ function fromFrontmatter(masked) {
199
+ const block = FRONTMATTER_RE.exec(masked);
200
+ if (!block)
201
+ return undefined;
202
+ for (const line of toLines(block[1])) {
203
+ const found = STATUS_LABEL_RE.exec(line);
204
+ // Read as YAML here and nowhere else: quotes and `#` are syntax in
205
+ // front-matter and characters in a sentence.
206
+ if (found)
207
+ return toStatus(yamlScalar(found[2]), 'frontmatter');
208
+ }
209
+ return undefined;
210
+ }
211
+ /**
212
+ * A `## Status` section, whose value is the first line of prose under it.
213
+ *
214
+ * A section with nothing but the next heading under it declares no status.
215
+ * There is no guard for that here: every ATX heading begins with `#`, and a
216
+ * value that does not begin with a letter is already no status at all. The
217
+ * guard this used to carry could not decide anything, which is a different
218
+ * thing from a guard that is merely never hit.
219
+ */
220
+ function fromHeading(lines) {
221
+ const start = lines.findIndex((line) => STATUS_HEADING_RE.test(line));
222
+ if (start === -1)
223
+ return undefined;
224
+ for (let index = start + 1; index < lines.length; index++) {
225
+ const candidate = lines[index].trim();
226
+ if (candidate.length === 0)
227
+ continue;
228
+ return toStatus(candidate, 'heading');
229
+ }
230
+ return undefined;
231
+ }
232
+ /**
233
+ * A `**Status:** accepted` line in the document's preamble.
234
+ *
235
+ * Bounded to the preamble - everything before the first `##` - because this
236
+ * form is a line of prose with a colon in it, and a tool that accepts one
237
+ * anywhere in a long document will eventually find one in a sentence.
238
+ */
239
+ function fromLabel(lines) {
240
+ for (const line of lines) {
241
+ if (SECTION_HEADING_RE.test(line))
242
+ return undefined;
243
+ const found = STATUS_LABEL_RE.exec(line);
244
+ if (found)
245
+ return toStatus(found[2], 'label');
246
+ }
247
+ return undefined;
248
+ }
249
+ /**
250
+ * The lifecycle status a Markdown document declares about itself.
251
+ *
252
+ * Three spellings are recognised because three are in use, including two in
253
+ * this repository's own ADRs: YAML front-matter (MADR), a `## Status` section
254
+ * (Nygard), and a bold `**Status:**` label. Front-matter wins when present -
255
+ * it is machine-readable metadata rather than a convention read out of prose.
256
+ *
257
+ * Code is masked first, so a document that documents this syntax inside a
258
+ * fence - this project's README does - is not read as declaring a status.
259
+ */
260
+ export function parseStatus(source) {
261
+ return statusOf(maskCode(source));
262
+ }
263
+ function statusOf(masked) {
264
+ const lines = toLines(masked);
265
+ return fromFrontmatter(masked) ?? fromHeading(lines) ?? fromLabel(lines);
266
+ }
91
267
  const DIRECTIVE_RE = /<!--\s*@([a-zA-Z][\w-]*)([\s\S]*?)-->/g;
92
268
  const ATTRIBUTE_RE = /([a-zA-Z][\w-]*)(?:\s*=\s*(?:"((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)'|([^\s"'=<>`]+)))?/g;
93
269
  /**
@@ -210,6 +386,7 @@ export function parseDirectives(source, context) {
210
386
  }
211
387
  directives.push({ kind: kind, attributes, location, raw });
212
388
  }
213
- return { directives, errors };
389
+ const status = statusOf(masked);
390
+ return status ? { directives, errors, status } : { directives, errors };
214
391
  }
215
392
  //# sourceMappingURL=parser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAKD,QAAA,MAAM,IAAI;aACR,KAAK;aACL,IAAI;aACJ,GAAG;aACH,GAAG;aACH,KAAK;aACL,MAAM;aACN,IAAI;aACJ,OAAO;aACP,IAAI;aACJ,IAAI;CACI,CAAC;AAEX,KAAK,KAAK,GAAG,MAAM,OAAO,IAAI,CAAC;AAE/B,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,MAAM,CAI1F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC3B,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAKT;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,QAAQ,kBAAmB,GAAG,OAAO,CAGzG;AA0JD,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,SAAI,GAAG,MAAM,CA8EjG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAezD;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAkDpD;AA2CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CA0EzF"}
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAKD,QAAA,MAAM,IAAI;aACR,KAAK;aACL,IAAI;aACJ,GAAG;aACH,GAAG;aACH,KAAK;aACL,MAAM;aACN,IAAI;aACJ,OAAO;aACP,IAAI;aACJ,IAAI;CACI,CAAC;AAEX,KAAK,KAAK,GAAG,MAAM,OAAO,IAAI,CAAC;AAE/B,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,MAAM,CAI1F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC3B,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAKT;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,QAAQ,kBAAmB,GAAG,OAAO,CAGzG;AA8JD,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,SAAI,GAAG,MAAM,CAmGjG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAezD;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAmDpD;AAiED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAwFzF"}
package/dist/reporter.js CHANGED
@@ -49,8 +49,8 @@ export function shouldUseAscii(env = process.env, platform = process.platform) {
49
49
  }
50
50
  function symbols(ascii) {
51
51
  return ascii
52
- ? { pass: '+', fail: 'x', warn: '!', more: '...' }
53
- : { pass: '✔', fail: '✖', warn: '⚠', more: '…' };
52
+ ? { pass: '+', fail: 'x', warn: '!', skip: 'o', more: '...' }
53
+ : { pass: '✔', fail: '✖', warn: '⚠', skip: '○', more: '…' };
54
54
  }
55
55
  function formatDuration(ms) {
56
56
  return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(2)}s`;
@@ -141,7 +141,11 @@ function formatFailure(result, paint, glyphs, maxSnippets) {
141
141
  function formatPass(result, paint, glyphs) {
142
142
  const detail = result.kind === 'assert-present'
143
143
  ? result.files.join(', ')
144
- : `"${result.symbol}" ${paint(`(${countLabel(result.actual, 'match')})`, 'dim')} in ${result.targets.join(', ')}`;
144
+ : result.symbol === undefined
145
+ ? // A cycle or layer rule has no symbol to quote, and its description
146
+ // already says what it is about and where.
147
+ `${result.description} ${paint(`(${countLabel(result.actual, result.kind === 'assert-import-cycle' ? 'cycle' : 'violating file')})`, 'dim')}`
148
+ : `"${result.symbol}" ${paint(`(${countLabel(result.actual, 'match')})`, 'dim')} in ${result.targets.join(', ')}`;
145
149
  return `${paint(glyphs.pass, 'green')} ${paint(formatLocation(result), 'dim')} ${paint(`@${result.kind}`, 'dim')} ${detail}`;
146
150
  }
147
151
  function formatError(error, paint, glyphs) {
@@ -209,16 +213,34 @@ export function formatReport(report, options, maxSnippets = 5) {
209
213
  lines.push(`${paint(glyphs.warn, 'yellow')} ${paint(note, 'yellow')}`);
210
214
  lines.push('');
211
215
  }
216
+ // Named, not totalled. A count of withheld rules tells a reader that some
217
+ // part of their specification stopped being enforced without telling them
218
+ // which part, and the whole reason to report this at all is that a rule
219
+ // going quiet is indistinguishable from a rule passing.
220
+ for (const spec of report.inactiveSpecs) {
221
+ const detail = spec.directives === 0
222
+ ? 'no directives to execute'
223
+ : `${countLabel(spec.directives, 'assertion')} not executed`;
224
+ lines.push(paint(`${glyphs.skip} ${spec.file} is ${spec.label} - ${detail}`, 'dim'));
225
+ }
226
+ if (report.inactiveSpecs.length > 0)
227
+ lines.push('');
212
228
  const parts = [
213
229
  paint(`${report.summary.passed} passed`, 'green'),
214
230
  failures.length > 0 ? paint(`${report.summary.failed} failed`, 'red', 'bold') : null,
215
231
  report.errors.length > 0 ? paint(`${report.errors.length} invalid`, 'yellow') : null,
216
232
  report.summary.skipped > 0 ? paint(`${report.summary.skipped} skipped`, 'dim') : null,
233
+ report.summary.inactive > 0 ? paint(`${report.summary.inactive} not in force`, 'dim') : null,
217
234
  paint(formatDuration(report.durationMs), 'dim'),
218
235
  ].filter((part) => part !== null);
219
236
  lines.push(parts.join(paint(' · ', 'dim')));
220
237
  if (report.ok) {
221
- lines.push(paint(`${glyphs.pass} every spec assertion holds`, 'green'));
238
+ // "Every assertion holds" over zero assertions is true and useless, and it
239
+ // is the exact sentence someone reads as proof their specification is
240
+ // being enforced. A run that verified nothing has to say so instead.
241
+ lines.push(report.summary.total > 0
242
+ ? paint(`${glyphs.pass} every spec assertion holds`, 'green')
243
+ : paint(`${glyphs.warn} no assertion was executed, so nothing was verified`, 'yellow'));
222
244
  }
223
245
  return lines.join('\n');
224
246
  }
@@ -302,6 +324,7 @@ export function formatJson(report) {
302
324
  raw: error.raw,
303
325
  })),
304
326
  warnings: report.warnings,
327
+ inactiveSpecs: report.inactiveSpecs,
305
328
  }, null, 2);
306
329
  }
307
330
  /* --------------------------------------------------------------------- sarif */
@@ -323,8 +346,28 @@ const SARIF_RULES = [
323
346
  { id: 'assert-present', text: 'A file or directory the specification says must exist.' },
324
347
  { id: 'assert-import-absence', text: 'A dependency one part of the codebase must not have.' },
325
348
  { id: 'assert-import-count', text: 'A dependency count one part of the codebase must hold to.' },
349
+ { id: 'assert-import-cycle', text: 'A set of files that depend on each other, directly or through others.' },
350
+ { id: 'assert-layers', text: 'A file importing from a layer the architecture places above it.' },
326
351
  { id: 'invalid-directive', text: 'A directive that could not be parsed, so nothing was checked.' },
327
352
  ];
353
+ /**
354
+ * SARIF's slot for "something happened during this run that is not a finding".
355
+ *
356
+ * A document that is not in force produces no result, and a format that only
357
+ * carries results would show a clean code-scanning page for a repository whose
358
+ * rules had gone dormant - the same silence the human report refuses. This is
359
+ * the standard's own answer to that: a note-level execution notification,
360
+ * which GitHub surfaces as run information rather than as an alert.
361
+ */
362
+ function inactiveNotifications(report) {
363
+ return report.inactiveSpecs.map((spec) => ({
364
+ level: 'note',
365
+ message: {
366
+ text: `${spec.file} is ${spec.label}, so ` +
367
+ `${spec.directives === 1 ? 'its 1 assertion was' : `its ${spec.directives} assertions were`} not executed.`,
368
+ },
369
+ }));
370
+ }
328
371
  function sarifLocation(uri, line, column, text) {
329
372
  const location = {
330
373
  physicalLocation: { artifactLocation: { uri }, region: { startLine: line, startColumn: column } },
@@ -371,7 +414,12 @@ export function formatSarif(report, options = {}) {
371
414
  specGuardAssertion: fingerprint([
372
415
  result.location.relativeFile,
373
416
  result.kind,
374
- result.symbol ?? result.files.join(','),
417
+ // The description only where there is nothing else to tell two
418
+ // assertions apart. A cycle or layer rule names no symbol and no
419
+ // file, so two on one target - `types="ignore"` beside the default -
420
+ // would share an identity and be merged into one alert. Every kind
421
+ // that has a symbol or a file list keeps the fingerprint it had.
422
+ result.symbol ?? (result.files.length > 0 ? result.files.join(',') : result.description),
375
423
  result.targets.join(','),
376
424
  ]),
377
425
  },
@@ -396,6 +444,15 @@ export function formatSarif(report, options = {}) {
396
444
  version: '2.1.0',
397
445
  runs: [
398
446
  {
447
+ // Present only when there is something to say. An empty invocations
448
+ // block is noise in every consumer that renders one.
449
+ ...(report.inactiveSpecs.length > 0
450
+ ? {
451
+ invocations: [
452
+ { executionSuccessful: report.ok, toolExecutionNotifications: inactiveNotifications(report) },
453
+ ],
454
+ }
455
+ : {}),
399
456
  tool: {
400
457
  driver: {
401
458
  name: 'spec-guard',