@descent-vtt/spec-guard 0.19.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +57 -24
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,40 @@ 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.19.1
|
|
14
|
+
|
|
15
|
+
The README's commands gave `npx` the command's bare name, which on npm is
|
|
16
|
+
not this project's package. spec-guard itself is unchanged.
|
|
17
|
+
|
|
18
|
+
### Security
|
|
19
|
+
|
|
20
|
+
- Every command in the README gives `npx` the package's full name behind
|
|
21
|
+
`--no-install`, as in `npx --no-install @descent-vtt/spec-guard ...`.
|
|
22
|
+
`spec-guard` without the scope belongs to nobody on npm (2026-10-07), so
|
|
23
|
+
anyone can register it.
|
|
24
|
+
`npx` given a name the project has not installed fetches the package of
|
|
25
|
+
that name and runs it, unasked when no terminal is attached: a fresh
|
|
26
|
+
clone, a worktree before `npm ci`, and the `mcpServers` entry the README
|
|
27
|
+
showed, which an MCP client starts with no terminal, wherever it stands.
|
|
28
|
+
[Names](README.md#names) says whose the names are; what was measured is in
|
|
29
|
+
the family's
|
|
30
|
+
[adopting guide](https://github.com/DescentVTT/spec-core/blob/main/docs/adopting.md#names).
|
|
31
|
+
Upgrading: where an `.mcp.json`, a hook, a CI job or a script gives `npx`
|
|
32
|
+
the command's name alone, write `npx --no-install @descent-vtt/spec-guard`;
|
|
33
|
+
in an MCP entry that is
|
|
34
|
+
`"args": ["--no-install", "@descent-vtt/spec-guard", "mcp", ...]`.
|
|
35
|
+
`--no-install` before the bare name is not enough: npm still runs a copy
|
|
36
|
+
of that name's package an earlier fetch left in its cache.
|
|
37
|
+
|
|
38
|
+
### Documentation
|
|
39
|
+
|
|
40
|
+
- The CI examples install the project and then run
|
|
41
|
+
`npx --no-install @descent-vtt/spec-guard`, as the family's adopting guide
|
|
42
|
+
has them. They ran `npx @descent-vtt/spec-guard` with no install, which
|
|
43
|
+
fetched whatever release was latest when the job ran; the lockfile now
|
|
44
|
+
pins it, as the same examples pin their actions to commits. A job written
|
|
45
|
+
the old way keeps working.
|
|
46
|
+
|
|
13
47
|
## 0.19.0
|
|
14
48
|
|
|
15
49
|
An engine named `constructor` or `__proto__` is refused as any unknown
|
package/README.md
CHANGED
|
@@ -51,23 +51,11 @@ build with a line number, not a landmine.
|
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
53
|
npm install --save-dev @descent-vtt/spec-guard
|
|
54
|
-
npx spec-guard "docs/**/*.md"
|
|
54
|
+
npx --no-install @descent-vtt/spec-guard "docs/**/*.md"
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
use that name:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npm install -g @descent-vtt/spec-guard # then: spec-guard "docs/**/*.md"
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Without a local install, `npx` needs the full package name - `npx spec-guard`
|
|
66
|
-
on its own would resolve to a different package on the registry:
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
npx @descent-vtt/spec-guard "docs/**/*.md"
|
|
70
|
-
```
|
|
57
|
+
`npx` is given the package's full name, here and in every command below:
|
|
58
|
+
[Names](#names) says why the command's name alone is not written.
|
|
71
59
|
|
|
72
60
|
Add a directive to any Markdown file, directly under the sentence it makes
|
|
73
61
|
executable:
|
|
@@ -83,7 +71,7 @@ Session state has exactly one owner.
|
|
|
83
71
|
Run it:
|
|
84
72
|
|
|
85
73
|
```bash
|
|
86
|
-
npx spec-guard "docs/**/*.md" --verbose
|
|
74
|
+
npx --no-install @descent-vtt/spec-guard "docs/**/*.md" --verbose
|
|
87
75
|
```
|
|
88
76
|
|
|
89
77
|
```text
|
|
@@ -110,6 +98,38 @@ And when it drifts:
|
|
|
110
98
|
|
|
111
99
|
Exit code 1. The ADR is now a test.
|
|
112
100
|
|
|
101
|
+
## Names
|
|
102
|
+
|
|
103
|
+
The package is `@descent-vtt/spec-guard`, and the command it installs is
|
|
104
|
+
`spec-guard`. The name without the scope is not this project: on npm,
|
|
105
|
+
`spec-guard` belonged to nobody on 2026-10-07, and whoever registers it decides
|
|
106
|
+
what it runs.
|
|
107
|
+
|
|
108
|
+
`npx` fetches and runs the package of whatever name it is given when the
|
|
109
|
+
project has none installed - a fresh clone, a worktree before `npm ci`, a CI job
|
|
110
|
+
without the install step - and without a terminal it does not ask first. So
|
|
111
|
+
give `npx` the full name:
|
|
112
|
+
|
|
113
|
+
- `npx --no-install @descent-vtt/spec-guard` in a project that installed it: it
|
|
114
|
+
runs that install, the version the lockfile pins, and where there is none it
|
|
115
|
+
stops with an error that names this package.
|
|
116
|
+
- `npx @descent-vtt/spec-guard`, without `--no-install`, where nothing is
|
|
117
|
+
installed: it fetches this package and runs it.
|
|
118
|
+
|
|
119
|
+
<!-- bare-name: the two forms in the next sentence are shown as what not to write -->
|
|
120
|
+
Never `npx spec-guard`, and not `npx --no-install spec-guard` either:
|
|
121
|
+
`--no-install` stops a download, and npm still runs a copy of the bare name's
|
|
122
|
+
package that an earlier fetch left in its cache. The family's
|
|
123
|
+
[adopting guide](https://github.com/DescentVTT/spec-core/blob/main/docs/adopting.md#names)
|
|
124
|
+
has what was measured, under npm 10, 11 and 12.
|
|
125
|
+
|
|
126
|
+
The command alone, `spec-guard`, is what a `package.json` script holds - npm
|
|
127
|
+
fetches nothing for a script - and what a global install puts on the path:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm install -g @descent-vtt/spec-guard # then: spec-guard "docs/**/*.md"
|
|
131
|
+
```
|
|
132
|
+
|
|
113
133
|
## Directives
|
|
114
134
|
|
|
115
135
|
Every directive is an HTML comment. It may span multiple lines. Attribute values
|
|
@@ -1015,12 +1035,16 @@ usual `mcpServers` entry is:
|
|
|
1015
1035
|
"mcpServers": {
|
|
1016
1036
|
"spec-guard": {
|
|
1017
1037
|
"command": "npx",
|
|
1018
|
-
"args": ["spec-guard", "mcp", "--spec", "docs/**/*.md"]
|
|
1038
|
+
"args": ["--no-install", "@descent-vtt/spec-guard", "mcp", "--spec", "docs/**/*.md"]
|
|
1019
1039
|
}
|
|
1020
1040
|
}
|
|
1021
1041
|
}
|
|
1022
1042
|
```
|
|
1023
1043
|
|
|
1044
|
+
A client starts a server with no terminal, wherever it stands, so the entry
|
|
1045
|
+
gives `npx` the package's [full name](#names) behind `--no-install`: in a tree
|
|
1046
|
+
without the install the server fails to start, and nothing is fetched.
|
|
1047
|
+
|
|
1024
1048
|
The root defaults to the directory the client starts the server in; pass
|
|
1025
1049
|
`--root` if yours starts servers somewhere else. On Windows, `npx` is a `.cmd`
|
|
1026
1050
|
script that a client spawning without a shell cannot launch; point `command` at
|
|
@@ -1432,13 +1456,21 @@ jobs:
|
|
|
1432
1456
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
1433
1457
|
with:
|
|
1434
1458
|
node-version: '22'
|
|
1435
|
-
- run:
|
|
1459
|
+
- run: npm ci
|
|
1460
|
+
- run: npx --no-install @descent-vtt/spec-guard "docs/**/*.md" "README.md" --verbose
|
|
1436
1461
|
```
|
|
1437
1462
|
|
|
1438
1463
|
The actions are pinned to commits, with the version beside each, because a tag
|
|
1439
1464
|
can be moved and a commit cannot; Dependabot's `github-actions` updates keep
|
|
1440
1465
|
pins like these current.
|
|
1441
1466
|
|
|
1467
|
+
spec-guard is pinned the same way, by the lockfile: `npm ci` installs the
|
|
1468
|
+
version it names, and `--no-install` behind the package's [full name](#names)
|
|
1469
|
+
stops the job where that install is missing, rather than fetching another. A
|
|
1470
|
+
repository with no JavaScript of its own keeps a `package.json` with
|
|
1471
|
+
`"private": true` and spec-guard as its only `devDependencies` entry, and
|
|
1472
|
+
commits the lockfile.
|
|
1473
|
+
|
|
1442
1474
|
That job needs nothing else installed. GitHub-hosted runners do **not** ship
|
|
1443
1475
|
ripgrep on `PATH` - spec-guard's own CI reports `engine: javascript` there - so
|
|
1444
1476
|
the fallback is what actually runs, and it produces identical results. If your
|
|
@@ -1464,10 +1496,10 @@ default `--engine auto`, a binary that cannot be run leaves the built-in
|
|
|
1464
1496
|
scanner to do the work, and the report's engine says `javascript`; under
|
|
1465
1497
|
`--engine rg` it is exit 2.
|
|
1466
1498
|
|
|
1467
|
-
As a pre-commit hook
|
|
1499
|
+
As a pre-commit hook, in a project that installed it:
|
|
1468
1500
|
|
|
1469
1501
|
```bash
|
|
1470
|
-
npx spec-guard "docs/**/*.md" --fail-fast
|
|
1502
|
+
npx --no-install @descent-vtt/spec-guard "docs/**/*.md" --fail-fast
|
|
1471
1503
|
```
|
|
1472
1504
|
|
|
1473
1505
|
### Annotations on the pull request
|
|
@@ -1481,8 +1513,8 @@ comment on the offending line:
|
|
|
1481
1513
|
security-events: write
|
|
1482
1514
|
actions: read # only in a private repository
|
|
1483
1515
|
steps:
|
|
1484
|
-
# ...checkout
|
|
1485
|
-
- run: npx @descent-vtt/spec-guard "docs/**/*.md" --format sarif > spec-guard.sarif || true
|
|
1516
|
+
# ...checkout, setup-node and npm ci as above
|
|
1517
|
+
- run: npx --no-install @descent-vtt/spec-guard "docs/**/*.md" --format sarif > spec-guard.sarif || true
|
|
1486
1518
|
- uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
|
1487
1519
|
with:
|
|
1488
1520
|
sarif_file: spec-guard.sarif
|
|
@@ -1518,7 +1550,8 @@ which a merge request shows beside its changes:
|
|
|
1518
1550
|
```yaml
|
|
1519
1551
|
spec-guard:
|
|
1520
1552
|
script:
|
|
1521
|
-
-
|
|
1553
|
+
- npm ci
|
|
1554
|
+
- npx --no-install @descent-vtt/spec-guard --format gitlab > gl-code-quality-report.json || true
|
|
1522
1555
|
artifacts:
|
|
1523
1556
|
reports:
|
|
1524
1557
|
codequality: gl-code-quality-report.json
|
|
@@ -1808,7 +1841,7 @@ fail, and `spec-guard cites` holds every ADR a comment in the code cites to
|
|
|
1808
1841
|
existing and being in force.
|
|
1809
1842
|
|
|
1810
1843
|
Line coverage is 100%, CI's full mutation sweep kills 99.14% of 12,333 mutants
|
|
1811
|
-
(0.19.
|
|
1844
|
+
(0.19.1), and every survivor a release adds is replayed before it ships
|
|
1812
1845
|
([ADR-0003](https://github.com/DescentVTT/spec-guard/blob/main/docs/adr/0003-mutation-testing.md));
|
|
1813
1846
|
[CONTRIBUTING.md](https://github.com/DescentVTT/spec-guard/blob/main/CONTRIBUTING.md)
|
|
1814
1847
|
has how to build, test and release, and
|