@descent-vtt/spec-guard 0.20.1 → 0.22.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.
- package/CHANGELOG.md +108 -0
- package/README.md +74 -16
- package/dist/cli.d.ts +4 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +155 -21
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -2
- package/dist/config.js.map +1 -1
- package/dist/engine.d.ts +9 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +32 -13
- package/dist/engine.js.map +1 -1
- package/dist/glob.d.ts +19 -1
- package/dist/glob.d.ts.map +1 -1
- package/dist/glob.js +40 -12
- package/dist/glob.js.map +1 -1
- package/dist/impact.d.ts +2 -0
- package/dist/impact.d.ts.map +1 -1
- package/dist/impact.js +1 -0
- package/dist/impact.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +22 -4
- package/dist/mcp.js.map +1 -1
- package/dist/prove.d.ts.map +1 -1
- package/dist/prove.js +1 -0
- package/dist/prove.js.map +1 -1
- package/dist/query.d.ts +4 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -1
- package/dist/query.js.map +1 -1
- package/dist/reporter.d.ts +16 -1
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +27 -3
- package/dist/reporter.js.map +1 -1
- package/dist/runner.d.ts +2 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +20 -3
- package/dist/runner.js.map +1 -1
- package/dist/specs.d.ts +14 -0
- package/dist/specs.d.ts.map +1 -1
- package/dist/specs.js +14 -5
- package/dist/specs.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +7 -2
- package/dist/watch.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,114 @@ what to do when upgrading; the family's policy, including how a flag or field
|
|
|
10
10
|
is deprecated before it goes, is spec-core's
|
|
11
11
|
[ADR-0009](https://github.com/DescentVTT/spec-core/blob/main/docs/adr/0009-versions-before-1-0.md).
|
|
12
12
|
|
|
13
|
+
## 0.22.0
|
|
14
|
+
|
|
15
|
+
A spec pattern that matches no file, beside others that do, is refused by
|
|
16
|
+
name, exit 2, where it was dropped without a word and the run reported on
|
|
17
|
+
the rest: a directory of specs that was renamed no longer leaves a green
|
|
18
|
+
check behind. `--allow-empty` lets such a pattern through, and `--watch` and
|
|
19
|
+
the server carry on and say which it is.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **A spec pattern that matches no file beside others that do is refused,
|
|
24
|
+
where it was dropped without a word.** A directory of specs that was
|
|
25
|
+
renamed left its pattern behind: its rules stopped running and the check
|
|
26
|
+
stayed green. A run, `prove`, `impact` and `query` now exit 2 with a line
|
|
27
|
+
that names each such pattern, from the command line or `specs`; documents a
|
|
28
|
+
script reads are still written, the JSON ones with the patterns as
|
|
29
|
+
`unmatchedSpecs`, and `--watch` and the server carry on and say which
|
|
30
|
+
pattern it is
|
|
31
|
+
([ADR-0014](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0014-configuration-and-watch.md)).
|
|
32
|
+
Upgrading: remove the pattern, or give `--allow-empty` to a run, `prove` or
|
|
33
|
+
`impact` where a pattern is meant to match nothing yet. `query` takes no
|
|
34
|
+
such option, so until the pattern is removed spec-harness's `context`
|
|
35
|
+
packet lists no rules and says why; its guard and its hooks ask spec-guard
|
|
36
|
+
nothing and are as they were.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- A ripgrep that failed is said once in a report. Under `--engine auto`, with
|
|
41
|
+
`SPEC_GUARD_RG` naming a program that is not ripgrep, the warning that the
|
|
42
|
+
scanner had answered was repeated for every group of searches, four times
|
|
43
|
+
for four rules over four targets; failures that differ are still each said.
|
|
44
|
+
- `FORCE_COLOR=false` turns colour off, as Node and `supports-color` read it,
|
|
45
|
+
where it forced colour on. Exactly `0` and `false` are off, on a terminal
|
|
46
|
+
too, and any other value still forces colour.
|
|
47
|
+
|
|
48
|
+
## 0.21.0
|
|
49
|
+
|
|
50
|
+
An input that is set and names nothing is refused, exit 2, by a line that
|
|
51
|
+
names it, where it was read as if it had not been given: an empty spec
|
|
52
|
+
pattern or `--root`, a root that is no directory, `--exclude ","`,
|
|
53
|
+
`--concurrency 0`, a value given to an option that takes none, and an
|
|
54
|
+
`--engine rg` whose binary is not ripgrep. A wrong command line is answered
|
|
55
|
+
in that one line, and no longer with the whole help after it.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- **An empty spec pattern is refused, where it was every spec under the
|
|
60
|
+
root.** `--spec ""`, or `""` for a pattern, was read as the root and ran
|
|
61
|
+
every Markdown file under it, for a run, `query`, `prove`, `cites`,
|
|
62
|
+
`impact` and the server; it is exit 2 and `invalid spec pattern "": it is
|
|
63
|
+
empty`, and `runSpecGuard` and the rest of the package throw the same
|
|
64
|
+
([ADR-0014](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0014-configuration-and-watch.md)).
|
|
65
|
+
Upgrading: write `.` where every Markdown file under the root is meant, and
|
|
66
|
+
have the shell refuse a variable that is not set, as `"${DOCS:?}"` does.
|
|
67
|
+
- **An empty `--root`, and a root that is not a directory, are refused by
|
|
68
|
+
every command.** `--root ""` ran in the working directory. A root that was
|
|
69
|
+
a file or was not there was "no spec files matched", which `--allow-empty`
|
|
70
|
+
made exit 0, `cites` exited 0 with nothing to look for, and the server
|
|
71
|
+
started; each is exit 2 and a line that names the root. Upgrading: name a
|
|
72
|
+
directory that exists, or leave the option out.
|
|
73
|
+
- **`--concurrency 0` is refused**, as `"concurrency": 0` in a configuration
|
|
74
|
+
always was; it ran as 1. Upgrading: write 1 or more, or leave it out for 8.
|
|
75
|
+
- **`--exclude` given separators and nothing else, as in `","`, is
|
|
76
|
+
refused**, where it cleared the configuration's list. Upgrading: `--exclude=`
|
|
77
|
+
with nothing still clears it.
|
|
78
|
+
- **An option that takes no value is refused with one.** What followed the
|
|
79
|
+
`=` was never read, so `--strict=false` was strict, `--default-skips=false`
|
|
80
|
+
kept the default skips, `--allow-empty=false` let an empty run through and
|
|
81
|
+
`--json=false` wrote JSON. Upgrading: give the option alone or leave it
|
|
82
|
+
out; `--no-strict`, `--no-default-skips` and the other opposites turn one
|
|
83
|
+
off.
|
|
84
|
+
- **`--engine rg` is refused where `SPEC_GUARD_RG` names no ripgrep that
|
|
85
|
+
runs, in a line that names the variable.** A program that answers
|
|
86
|
+
`--version` and is not ripgrep was taken for one: every search failed, the
|
|
87
|
+
scanner answered, and the run exited 0 with a warning for each. A path that
|
|
88
|
+
was not there was blamed on `PATH`, and on Windows a file that is no
|
|
89
|
+
program ended the run with `spawn EFTYPE`. Each is exit 2 before anything
|
|
90
|
+
is searched, and `findRipgrep()` from the package answers `null` for each
|
|
91
|
+
([ADR-0004](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0004-adaptive-engine.md)).
|
|
92
|
+
Upgrading: set the variable to the path of an `rg` that runs, unset it to
|
|
93
|
+
use the one on `PATH`, or leave `--engine rg` out: `auto` still leaves a
|
|
94
|
+
binary it cannot use to the scanner.
|
|
95
|
+
- **`FORCE_COLOR=0` and `TERM=dumb` turn colour off on a terminal**, as the
|
|
96
|
+
family reads them (spec-core's
|
|
97
|
+
[ADR-0005](https://github.com/DescentVTT/spec-core/blob/main/docs/adr/0005-the-family-contract.md)).
|
|
98
|
+
`FORCE_COLOR=0` only declined to force colour, and `TERM` was not read for
|
|
99
|
+
colour, so a terminal that says it draws none was written escapes. Any
|
|
100
|
+
other `FORCE_COLOR` and `--color` still force it, over `TERM=dumb` too.
|
|
101
|
+
Upgrading: unset the variable, or pass `--color`.
|
|
102
|
+
|
|
103
|
+
### Fixed
|
|
104
|
+
|
|
105
|
+
- A wrong command line is answered in one line, `spec-guard:` and what was
|
|
106
|
+
wrong, as every other refusal is. The whole help followed it, a hundred
|
|
107
|
+
lines, so the reason was the first line of a log that is read from its
|
|
108
|
+
end. Exit 2, as before; `spec-guard --help` prints the help.
|
|
109
|
+
- A `package.json` or `.spec-guard.json` that is not JSON is refused in one
|
|
110
|
+
line. The parser quotes a short file whole, line breaks and all, so a file
|
|
111
|
+
of three lines made a refusal of three; each run of line breaks and spaces
|
|
112
|
+
in what it says is now one space. Exit 2, as before.
|
|
113
|
+
|
|
114
|
+
### Documentation
|
|
115
|
+
|
|
116
|
+
- `--help` and the README's options table name `SPEC_GUARD_RG` beside
|
|
117
|
+
`--engine`, and `FORCE_COLOR` and `TERM=dumb` beside `--color`, and say
|
|
118
|
+
that `NO_COLOR`, `FORCE_COLOR` or `SPEC_GUARD_RG` set to nothing is as
|
|
119
|
+
unset.
|
|
120
|
+
|
|
13
121
|
## 0.20.1
|
|
14
122
|
|
|
15
123
|
A reader that closed the output, as `| head` does, was answered with
|
package/README.md
CHANGED
|
@@ -1064,6 +1064,13 @@ instructions tell an agent when to call each: the rules before creating or
|
|
|
1064
1064
|
changing a file, the dependents before changing a file others import, and the
|
|
1065
1065
|
check after changing files.
|
|
1066
1066
|
|
|
1067
|
+
The server starts whatever its patterns match, since a spec may be written
|
|
1068
|
+
while it runs. Where no spec file matches, the first two tools answer with an
|
|
1069
|
+
error that names the patterns. Where one pattern matches none beside others
|
|
1070
|
+
that do, each answer is given from the rest and ends by naming the pattern it
|
|
1071
|
+
holds no rule from, with `unmatchedSpecs` in its structured content and in
|
|
1072
|
+
`spec://rules`.
|
|
1073
|
+
|
|
1067
1074
|
| Resource | What it holds |
|
|
1068
1075
|
| --- | --- |
|
|
1069
1076
|
| `spec://rules` | Every rule in force, as JSON |
|
|
@@ -1251,7 +1258,9 @@ src/db/client.ts
|
|
|
1251
1258
|
- **Exit 2** for a path that does not exist, and for a run of `impact` in which
|
|
1252
1259
|
no spec matched, as `query` does: the dependents are still written, but "no
|
|
1253
1260
|
rules" over no specs is nothing measured. `--allow-empty` asks for the
|
|
1254
|
-
dependents alone, and exits 0.
|
|
1261
|
+
dependents alone, and exits 0. A spec pattern that matched no file beside
|
|
1262
|
+
others that did is the same: the dependents and the rules that were read
|
|
1263
|
+
are written, and it is exit 2 unless `--allow-empty`.
|
|
1255
1264
|
- **The MCP server** answers the same question as `get_dependents`, with the
|
|
1256
1265
|
same document.
|
|
1257
1266
|
[ADR-0018](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0018-impact.md) has the table and what it leaves out.
|
|
@@ -1270,27 +1279,27 @@ spec-guard impact <paths...> # the files that depend on each path, and
|
|
|
1270
1279
|
|
|
1271
1280
|
| Option | Description |
|
|
1272
1281
|
| --- | --- |
|
|
1273
|
-
| `-r, --root <path>` | Codebase root that assertions resolve against (default: cwd) |
|
|
1274
|
-
| `--spec <pattern>` | A spec glob or path, repeatable. `query` and `mcp` take their specs only from here |
|
|
1282
|
+
| `-r, --root <path>` | Codebase root that assertions resolve against, a directory (default: cwd). One that is not there, or is a file, is exit 2 from every command |
|
|
1283
|
+
| `--spec <pattern>` | A spec glob or path, repeatable. `query` and `mcp` take their specs only from here. An empty one is refused: `.` is every Markdown file under the root. So is one that matches no file beside others that do (below) |
|
|
1275
1284
|
| `-v, --verbose` | Print passing assertions too |
|
|
1276
1285
|
| `--watch` | Report, then report again as the tree changes, until Ctrl+C |
|
|
1277
1286
|
| `--fail-fast` | Stop at the first failing assertion |
|
|
1278
1287
|
| `--json` | Machine-readable report on stdout (same as `--format json`), versioned by `formatVersion` |
|
|
1279
1288
|
| `--format <human\|json\|sarif\|github\|gitlab>` | Output format. `sarif` uploads to GitHub code scanning, `github` annotates a pull request from the job's log, `gitlab` is a GitLab Code Quality report |
|
|
1280
|
-
| `--engine <auto\|rg\|js>` | Search engine (default `auto`: scanner for small trees, ripgrep for big ones) |
|
|
1289
|
+
| `--engine <auto\|rg\|js>` | Search engine (default `auto`: scanner for small trees, ripgrep for big ones). ripgrep is `rg` on `PATH`, or the program `SPEC_GUARD_RG` names; `rg` with no ripgrep that runs is exit 2 ([below](#ci-integration)) |
|
|
1281
1290
|
| `--strict` / `--no-strict` | Treat analysis that could not be completed as a failure, and a run that executed no assertion: its specs matched and state no rule in force |
|
|
1282
1291
|
| `--allow-missing-targets` / `--no-allow-missing-targets` | Warn instead of failing when a `target` path does not exist |
|
|
1283
1292
|
| `--allow-empty-scope` / `--no-allow-empty-scope` | Warn instead of failing when an assertion inspects no files |
|
|
1284
1293
|
| `--print-baseline` | Print the `baseline="..."` that would exempt today's violations, and exit |
|
|
1285
1294
|
| `--no-default-skips` / `--default-skips` | Search `.git`, `.hg`, `.svn` and `node_modules` too |
|
|
1286
|
-
| `--exclude <globs>` | Paths no assertion looks at, beside each directive's own `exclude`. Repeatable; replaces the configuration's list, and `--exclude=` clears it |
|
|
1295
|
+
| `--exclude <globs>` | Paths no assertion looks at, beside each directive's own `exclude`. Repeatable; replaces the configuration's list, and `--exclude=` clears it. Separators with nothing between them, `","`, are refused |
|
|
1287
1296
|
| `--ignore-status` / `--no-ignore-status` | Execute directives in documents not in force too: draft, proposed, rejected, deprecated, superseded or archived |
|
|
1288
1297
|
| `--include-specs` / `--no-include-specs` | Also count matches inside the spec files themselves |
|
|
1289
1298
|
| `--max-snippets <n>` | Failure snippets per assertion (default 5) |
|
|
1290
|
-
| `--concurrency <n>` | Search passes in flight at once (default 8) |
|
|
1299
|
+
| `--concurrency <n>` | Search passes in flight at once, 1 or more (default 8) |
|
|
1291
1300
|
| `--depth <n>` | `impact` only: follow dependents at most `n` imports away (default: all) |
|
|
1292
|
-
| `--allow-empty` |
|
|
1293
|
-
| `--color` / `--no-color` | Force colour on or off
|
|
1301
|
+
| `--allow-empty` | Let a run, `prove` or `impact` through when no spec file matched the patterns, or when one pattern matched none beside others that did, each of which is exit 2 without it; such a pattern is still named on stderr (about the run, not an assertion) |
|
|
1302
|
+
| `--color` / `--no-color` | Force colour on or off. Without either flag, `NO_COLOR` set to anything turns it off; otherwise `FORCE_COLOR` turns it on, and `FORCE_COLOR=0` or `FORCE_COLOR=false` off; otherwise `TERM=dumb` turns it off; otherwise a terminal has colour. `NO_COLOR` or `FORCE_COLOR` set to nothing is as unset |
|
|
1294
1303
|
|
|
1295
1304
|
Patterns are expanded by spec-guard itself, so quoted globs behave identically
|
|
1296
1305
|
on Windows, macOS and Linux. A directory expands to the Markdown files in it.
|
|
@@ -1301,6 +1310,41 @@ An option that means nothing to a command is refused rather than ignored, so
|
|
|
1301
1310
|
`--no-color`: its output never has colour, and scripts pass the flag to every
|
|
1302
1311
|
command they run.
|
|
1303
1312
|
|
|
1313
|
+
So is an option that is set and names nothing, which is exit 2 and a line
|
|
1314
|
+
that names it, never a run as if it had not been given. `--root "$DIR"` and
|
|
1315
|
+
`--spec "$DOCS"` with the variable unset were the working directory and every
|
|
1316
|
+
Markdown file under the root; `--concurrency 0` was 1; and an option that is
|
|
1317
|
+
on when it is given was on whatever followed its `=`, so `--strict=false` was
|
|
1318
|
+
strict and `--allow-empty=false` let an empty run through. An option a
|
|
1319
|
+
configuration can set has an opposite to turn it off, `--no-strict`; any
|
|
1320
|
+
other is left out.
|
|
1321
|
+
|
|
1322
|
+
And so is a spec pattern that matches no file beside others that do. After
|
|
1323
|
+
`old-docs` was renamed, `spec-guard docs old-docs` ran the specs under `docs`
|
|
1324
|
+
and said nothing of the rest: every rule in the renamed directory had stopped
|
|
1325
|
+
running, and the check was green. A run, `prove`, `impact` and `query` now
|
|
1326
|
+
exit 2 with one line that names each such pattern, wherever it was written, on
|
|
1327
|
+
the command line or in `specs`:
|
|
1328
|
+
|
|
1329
|
+
```text
|
|
1330
|
+
spec-guard: the pattern "old-docs" matched no spec file. Remove it from "specs" in package.json, or give --allow-empty where a pattern is meant to match nothing.
|
|
1331
|
+
```
|
|
1332
|
+
|
|
1333
|
+
- **`--allow-empty`** lets a run, `prove` or `impact` through, for a place
|
|
1334
|
+
nothing is written in yet, and the pattern is still named on stderr.
|
|
1335
|
+
`query` takes no such option.
|
|
1336
|
+
- **A document a script reads is still written**, by `--json`,
|
|
1337
|
+
`--format sarif` and `--format gitlab`, and the JSON ones carry the
|
|
1338
|
+
patterns as `unmatchedSpecs`. The key is there only when a pattern matched
|
|
1339
|
+
no file, and `formatVersion` stays 1: a field added does not move it.
|
|
1340
|
+
- **`--watch` and `mcp` carry on**, since the file may yet appear. A session
|
|
1341
|
+
says which pattern it is waiting on under each report, and each answer the
|
|
1342
|
+
server gives names the pattern it holds no rule from, with `unmatchedSpecs`
|
|
1343
|
+
in its structured content.
|
|
1344
|
+
- **No spec at all is as it was**: `no spec files matched ...`, exit 2, or 0
|
|
1345
|
+
under `--allow-empty`. So is `docs/**/*.md`, the pattern read when none is
|
|
1346
|
+
given, which is alone and so matches or leaves no spec at all.
|
|
1347
|
+
|
|
1304
1348
|
### Configuration
|
|
1305
1349
|
|
|
1306
1350
|
The options that are a project's policy can live in `package.json`, under
|
|
@@ -1415,7 +1459,9 @@ goes.
|
|
|
1415
1459
|
|
|
1416
1460
|
`--watch` scans in-process, where it can see what each rule reads, so it refuses
|
|
1417
1461
|
`--engine`, and `--json`, `--format json|sarif`, `--print-baseline`,
|
|
1418
|
-
`--fail-fast` and `--allow-empty`, which each describe a single run.
|
|
1462
|
+
`--fail-fast` and `--allow-empty`, which each describe a single run. A spec
|
|
1463
|
+
pattern that matches no file does not stop a session: it waits for one to
|
|
1464
|
+
appear, and says which pattern that is under each report. It exits
|
|
1419
1465
|
130 when stopped, since a session is neither a pass nor a failure. What it
|
|
1420
1466
|
cannot see: a change the operating system never reports, a change behind a
|
|
1421
1467
|
symbolic link, and anything outside the root. CI stays the authority.
|
|
@@ -1431,7 +1477,7 @@ should be able to tell them apart, so they are 1 and 2:
|
|
|
1431
1477
|
| `1` | An assertion failed, or a directive was malformed; under `--strict`, the specs matched state no rule in force, so no assertion was executed |
|
|
1432
1478
|
| `1`, `prove` | A rule survived, or under `--strict` none was proved |
|
|
1433
1479
|
| `1`, `cites` | A comment cites a document that does not exist, or under `--strict` a citation is stale, a file was read in part, or no source file was read |
|
|
1434
|
-
| `2` | spec-guard could not run, or its answer did not arrive: bad usage, a malformed configuration, no spec files matched, `--engine rg` with no ripgrep, a watch that could not start, a `cites` family whose files match no document, a stdout its reader closed before all of the output was written, as a pipeline into `head` does, said in one line on stderr, or an error spec-guard did not expect, reported on stderr as `spec-guard: unexpected error:` with its stack |
|
|
1480
|
+
| `2` | spec-guard could not run, or its answer did not arrive: bad usage, an option set to something that names nothing, a root that is not a directory, a malformed configuration, no spec files matched, a spec pattern that matched none beside others that did, `--engine rg` with no ripgrep, a watch that could not start, a `cites` family whose files match no document, a stdout its reader closed before all of the output was written, as a pipeline into `head` does, said in one line on stderr, or an error spec-guard did not expect, reported on stderr as `spec-guard: unexpected error:` with its stack |
|
|
1435
1481
|
| `130` | A `--watch` session was stopped |
|
|
1436
1482
|
|
|
1437
1483
|
## CI integration
|
|
@@ -1491,10 +1537,22 @@ runs:
|
|
|
1491
1537
|
| Windows | `winget install BurntSushi.ripgrep.MSVC` |
|
|
1492
1538
|
|
|
1493
1539
|
spec-guard looks for `rg` on `PATH`. `SPEC_GUARD_RG=/path/to/rg` names the
|
|
1494
|
-
binary instead, for one that is not on `PATH` or not called `rg
|
|
1495
|
-
default `--engine auto`, a binary that
|
|
1496
|
-
scanner to do the work, and the report's
|
|
1497
|
-
`--engine rg`
|
|
1540
|
+
binary instead, for one that is not on `PATH` or not called `rg`; set to
|
|
1541
|
+
nothing, it is as unset. Under the default `--engine auto`, a binary that
|
|
1542
|
+
cannot be run leaves the built-in scanner to do the work, and the report's
|
|
1543
|
+
engine says `javascript`. `--engine rg`, or `"engine": "rg"` in the
|
|
1544
|
+
configuration, is ripgrep asked for, and a run that cannot have it is exit 2
|
|
1545
|
+
before anything is searched, never a run on the scanner: where the variable
|
|
1546
|
+
names a path that is not there, a file that is no program, or a program that
|
|
1547
|
+
does not answer `--version` as ripgrep does, the line names the variable and
|
|
1548
|
+
what it holds:
|
|
1549
|
+
|
|
1550
|
+
```text
|
|
1551
|
+
spec-guard: SPEC_GUARD_RG is "/opt/tools/rg", which did not answer --version as ripgrep does, and the rg engine was asked for. Set it to the path of an rg that runs, or unset it to use the rg on PATH.
|
|
1552
|
+
```
|
|
1553
|
+
|
|
1554
|
+
A program that runs and is not ripgrep fails each search `auto` hands it; the
|
|
1555
|
+
scanner answers that search, and the report carries a warning for it.
|
|
1498
1556
|
|
|
1499
1557
|
As a pre-commit hook, in a project that installed it:
|
|
1500
1558
|
|
|
@@ -1840,8 +1898,8 @@ build fails if they stop being true. CI proves every one of those rules can
|
|
|
1840
1898
|
fail, and `spec-guard cites` holds every ADR a comment in the code cites to
|
|
1841
1899
|
existing and being in force.
|
|
1842
1900
|
|
|
1843
|
-
Line coverage is 100%, CI's full mutation sweep kills 99.
|
|
1844
|
-
(0.
|
|
1901
|
+
Line coverage is 100%, CI's full mutation sweep kills 99.23% of 12,580 mutants
|
|
1902
|
+
(0.22.0), and every survivor a release adds is replayed before it ships
|
|
1845
1903
|
([ADR-0003](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0003-mutation-testing.md));
|
|
1846
1904
|
[CONTRIBUTING.md](https://github.com/DescentVTT/spec-guard/blob/main/CONTRIBUTING.md)
|
|
1847
1905
|
has how to build, test and release, and
|
package/dist/cli.d.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* 0 - every assertion held
|
|
6
6
|
* 1 - an assertion failed, a directive was invalid, or under --strict no
|
|
7
7
|
* assertion was executed
|
|
8
|
-
* 2 - spec-guard could not run (bad usage, no spec files,
|
|
9
|
-
*
|
|
8
|
+
* 2 - spec-guard could not run (bad usage, no spec files, a spec pattern
|
|
9
|
+
* that matched none beside others that did, missing engine), or met an
|
|
10
|
+
* error it did not expect, whose stack is on stderr
|
|
10
11
|
*/
|
|
11
12
|
import type { Readable } from 'node:stream';
|
|
12
13
|
import { type ConfigKey, type ProjectConfig } from './config.js';
|
|
@@ -94,7 +95,7 @@ export declare class UsageError extends Error {
|
|
|
94
95
|
* fallback nobody knows still works.
|
|
95
96
|
*/
|
|
96
97
|
export declare function version(manifest?: string): string;
|
|
97
|
-
export declare const HELP = "spec-guard - Executable architecture assertions for Markdown specs & ADRs\n\nUsage\n spec-guard [patterns...] [options] execute the directives in the specs\n spec-guard query <paths...> [options] list the rules in force for files or directories\n spec-guard mcp [options] serve the rules to an AI agent over MCP on stdio\n spec-guard prove [patterns...] [options]\n show each rule a violation of itself, in memory, and report any that pass\n spec-guard cites [paths...] [options] check that each spec a code comment cites exists and is in force\n spec-guard impact <paths...> [options] the files that depend on each path, and the rules in play there\n\nPatterns\n Globs or paths to the Markdown specs to execute. A directory expands to the\n Markdown files inside it. Defaults to \"docs/**/*.md\" when omitted. query,\n mcp, cites and impact take theirs from --spec.\n\nOptions\n -r, --root <path> Codebase root that assertions are resolved against (default: cwd)\n --spec <pattern> A spec glob or path; repeatable (default: \"docs/**/*.md\")\n -v, --verbose Print passing assertions too\n --watch Run again as the tree changes, until Ctrl+C (human output only)\n --fail-fast Stop at the first failing assertion\n --json Emit a machine-readable JSON report (same as --format json)\n --format <name> human | json | sarif | github | gitlab (sarif uploads to code scanning,\n github annotates a pull request from the log, gitlab is Code Quality)\n --engine <name> auto | rg | js (default: auto - scanner for small trees, ripgrep for big ones)\n --strict Treat analysis that could not be completed, and a run that\n executed no assertion, as a failure\n --allow-missing-targets\n Tolerate target paths that do not exist (they fail by default)\n --allow-empty-scope Tolerate assertions whose scope holds no files (they fail by default)\n --print-baseline Print the baseline=\"...\" that would exempt today's violations, and exit\n --no-default-skips Search .git, .hg, .svn and node_modules too\n --exclude <globs> Paths no assertion looks at, beside each directive's exclude; repeatable\n --ignore-status Execute directives in documents not in force too (see Directives)\n --include-specs Also count matches inside the spec files themselves\n --max-snippets <n> Failure snippets per assertion (default: 5)\n --concurrency <n> Assertions executed in parallel (default: 8)\n --depth <n> impact: follow dependents at most n imports away (default: all)\n --allow-empty
|
|
98
|
+
export declare const HELP = "spec-guard - Executable architecture assertions for Markdown specs & ADRs\n\nUsage\n spec-guard [patterns...] [options] execute the directives in the specs\n spec-guard query <paths...> [options] list the rules in force for files or directories\n spec-guard mcp [options] serve the rules to an AI agent over MCP on stdio\n spec-guard prove [patterns...] [options]\n show each rule a violation of itself, in memory, and report any that pass\n spec-guard cites [paths...] [options] check that each spec a code comment cites exists and is in force\n spec-guard impact <paths...> [options] the files that depend on each path, and the rules in play there\n\nPatterns\n Globs or paths to the Markdown specs to execute. A directory expands to the\n Markdown files inside it. Defaults to \"docs/**/*.md\" when omitted. query,\n mcp, cites and impact take theirs from --spec.\n\nOptions\n -r, --root <path> Codebase root that assertions are resolved against, a directory (default: cwd)\n --spec <pattern> A spec glob or path; repeatable (default: \"docs/**/*.md\")\n -v, --verbose Print passing assertions too\n --watch Run again as the tree changes, until Ctrl+C (human output only)\n --fail-fast Stop at the first failing assertion\n --json Emit a machine-readable JSON report (same as --format json)\n --format <name> human | json | sarif | github | gitlab (sarif uploads to code scanning,\n github annotates a pull request from the log, gitlab is Code Quality)\n --engine <name> auto | rg | js (default: auto - scanner for small trees, ripgrep for big ones)\n ripgrep is rg on PATH, or the program SPEC_GUARD_RG names; where that\n is no ripgrep that runs, rg is exit 2 and auto leaves it to the scanner\n --strict Treat analysis that could not be completed, and a run that\n executed no assertion, as a failure\n --allow-missing-targets\n Tolerate target paths that do not exist (they fail by default)\n --allow-empty-scope Tolerate assertions whose scope holds no files (they fail by default)\n --print-baseline Print the baseline=\"...\" that would exempt today's violations, and exit\n --no-default-skips Search .git, .hg, .svn and node_modules too\n --exclude <globs> Paths no assertion looks at, beside each directive's exclude; repeatable\n --ignore-status Execute directives in documents not in force too (see Directives)\n --include-specs Also count matches inside the spec files themselves\n --max-snippets <n> Failure snippets per assertion (default: 5)\n --concurrency <n> Assertions executed in parallel, 1 or more (default: 8)\n --depth <n> impact: follow dependents at most n imports away (default: all)\n --allow-empty Let a run, prove or impact through when no spec file matched, or when\n one pattern matched none beside others that did (not an assertion)\n --color/--no-color Force colour on or off (NO_COLOR, FORCE_COLOR and TERM=dumb are honoured)\n -h, --help Show this help\n --version Print the version\n\n An option that is set and names nothing is refused, exit 2, never read as if\n it were not there: an empty --root or spec pattern, --exclude \",\" (--exclude=\n with nothing clears the list), --concurrency 0, a root that is no directory,\n and a value given to an option that takes none, as in --strict=false.\n\n A spec pattern that matches no file, beside others that do, is refused the\n same way and by name, since none of its rules was read: a run, prove, impact\n and query exit 2. --allow-empty lets the first three through and still names\n it; --watch and mcp carry on, and say which pattern it is.\n\nConfiguration\n package.json in the root can hold specs, exclude, engine, strict,\n allowMissingTargets, allowEmptyScope, ignoreStatus, includeSpecs, defaultSkips,\n maxSnippets and concurrency under \"specGuard\"; a root with no package.json can\n keep them in .spec-guard.json instead, but not in both. A flag wins over the\n file, every on/off option there also takes its opposite (--no-strict,\n --default-skips, ...), and --exclude= with nothing clears exclude.\n \"cites\": [{ \"id\": \"ADR-{n}\", \"files\": \"docs/adr/{n}-*.md\" }] names the\n documents code comments cite; without it, cites reads them off the titles of\n numbered specs.\n\nDirectives\n <!-- @assert-absence target=\"src/\" symbol=\"LegacyGateway\" exclude=\"src/legacy/**\" -->\n <!-- @assert-count target=\"src/\" symbol=\"SessionManager\" expected=\"1\" -->\n <!-- @assert-present file=\"SECURITY.md\" -->\n <!-- @assert-import-cycle target=\"src/\" types=\"ignore\" -->\n <!-- @assert-layers target=\"src/\" order=\"domain, application, infrastructure\" -->\n <!-- @assert-structure target=\"src/\" exclude=\"*.test.ts\" partner=\"[name].test.ts\" -->\n\n Matches inside comments do not count; add comments=\"include\" to count them.\n An assertion whose scope holds no files fails; add allow-empty=\"true\" to allow it.\n A document whose status is draft, proposed, rejected, deprecated, superseded\n or archived is reported and not executed; --ignore-status runs it anyway.\n The status is read in English, whatever language the document is written in:\n status: superseded.\n\nprove adds, changes or removes files in memory only - never on disk - to make\nthe violation each rule forbids, and runs the rule over that tree. A rule that\nstill passes survived, and exits 1; one no violation could be made for is\nunprovable, and exits 1 under --strict.\n\ncites reads comment text only - not strings, not Markdown - for ids such as\nADR-0007, ADR-7 and ADR-007, which are one document. A ghost citation names no\ndocument, and exits 1; a stale one names a document superseded, deprecated,\nrejected or archived, and exits 1 under --strict. A family whose files match no\ndocument exits 2.\n\nimpact follows the import graph backwards: relative JavaScript, TypeScript and\nPython imports that name a file. Go, Rust, C# and absolute Python imports name\nmodules, and are counted rather than followed; an import that names no file is\nlisted, never guessed at.\n\nquery answers from the specs alone, without reading the codebase, so it works\nfor a file that does not exist yet. mcp offers the same answer, a check and\nimpact's, as the tools get_architectural_rules, check_architecture and\nget_dependents.\n\nExit codes\n 0 all assertions passed 1 an assertion failed, or none ran under --strict\n 2 spec-guard could not run 130 a --watch session was stopped";
|
|
98
99
|
/** Minimal, dependency-free argv parser. Supports `--flag value` and `--flag=value`. */
|
|
99
100
|
export declare function parseArgs(argv: readonly string[], cwd: string): CliOptions;
|
|
100
101
|
/**
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|