@descent-vtt/spec-guard 0.7.0 → 0.9.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 +147 -0
- package/README.md +224 -27
- package/dist/cli.d.ts +37 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +275 -59
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +66 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +165 -0
- package/dist/config.js.map +1 -0
- package/dist/engine.d.ts +22 -8
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +118 -67
- package/dist/engine.js.map +1 -1
- package/dist/facts.d.ts +106 -0
- package/dist/facts.d.ts.map +1 -0
- package/dist/facts.js +188 -0
- package/dist/facts.js.map +1 -0
- package/dist/glob.d.ts +17 -21
- package/dist/glob.d.ts.map +1 -1
- package/dist/glob.js +13 -24
- package/dist/glob.js.map +1 -1
- package/dist/imports.d.ts +6 -1
- package/dist/imports.d.ts.map +1 -1
- package/dist/imports.js +9 -5
- package/dist/imports.js.map +1 -1
- package/dist/index.d.ts +20 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/dist/io.d.ts +51 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +44 -0
- package/dist/io.js.map +1 -0
- package/dist/mcp.d.ts +11 -0
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +23 -18
- package/dist/mcp.js.map +1 -1
- package/dist/memo.d.ts +53 -0
- package/dist/memo.d.ts.map +1 -0
- package/dist/memo.js +67 -0
- package/dist/memo.js.map +1 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +17 -0
- package/dist/parser.js.map +1 -1
- package/dist/query.d.ts +5 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +12 -3
- package/dist/query.js.map +1 -1
- package/dist/reporter.d.ts +10 -0
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +33 -4
- package/dist/reporter.js.map +1 -1
- package/dist/rules.d.ts +12 -1
- package/dist/rules.d.ts.map +1 -1
- package/dist/rules.js +45 -1
- package/dist/rules.js.map +1 -1
- package/dist/runner.d.ts +42 -2
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +261 -76
- package/dist/runner.js.map +1 -1
- package/dist/specs.d.ts +3 -1
- package/dist/specs.d.ts.map +1 -1
- package/dist/specs.js +6 -5
- package/dist/specs.js.map +1 -1
- package/dist/structure.d.ts +104 -0
- package/dist/structure.d.ts.map +1 -0
- package/dist/structure.js +254 -0
- package/dist/structure.js.map +1 -0
- package/dist/types.d.ts +50 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/watch.d.ts +125 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +321 -0
- package/dist/watch.js.map +1 -0
- package/package.json +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,153 @@ All notable changes to this project are documented here. Versions follow
|
|
|
5
5
|
may change in a minor release — each such change is listed under **Changed**
|
|
6
6
|
with the flag that restores the previous behaviour.
|
|
7
7
|
|
|
8
|
+
## 0.9.0
|
|
9
|
+
|
|
10
|
+
A project's policy can live in its `package.json`, and `spec-guard --watch`
|
|
11
|
+
reports again as the tree changes, re-executing only the rules a change
|
|
12
|
+
affected. [ADR-0014](docs/adr/0014-configuration-and-watch.md).
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Options in `package.json`, under `"specGuard"`:** `specs`, `engine`,
|
|
17
|
+
`strict`, `allowMissingTargets`, `allowEmptyScope`, `ignoreStatus`,
|
|
18
|
+
`includeSpecs`, `defaultSkips`, `maxSnippets` and `concurrency`.
|
|
19
|
+
- Read from the root's `package.json` only, never a parent directory's.
|
|
20
|
+
- Validated before anything runs. An unknown key, an option that belongs to one
|
|
21
|
+
invocation (`format`, `verbose`, `watch`, ...), a string where a boolean goes
|
|
22
|
+
or a count out of range is exit 2, naming the file and the key. `--help` and
|
|
23
|
+
`--version` still work under a broken `package.json`.
|
|
24
|
+
- The command line wins: patterns replace `specs`, and every on/off option the
|
|
25
|
+
file can set gained its opposite - `--no-strict`,
|
|
26
|
+
`--no-allow-missing-targets`, `--no-allow-empty-scope`, `--no-ignore-status`,
|
|
27
|
+
`--no-include-specs` and `--default-skips`.
|
|
28
|
+
- A report that took anything from the file names it in a line above its
|
|
29
|
+
summary, with what the command line overrode; the JSON report carries
|
|
30
|
+
`config`.
|
|
31
|
+
- `query` applies the keys a query reads. The MCP server reads the file again
|
|
32
|
+
for every request, as it reads the specs.
|
|
33
|
+
- **`spec-guard --watch`.** Reports, then reports again whenever something under
|
|
34
|
+
the root changes, until Ctrl+C, which exits 130.
|
|
35
|
+
- Saves are batched: 50 ms of quiet, or 500 ms after the first change. Enter
|
|
36
|
+
re-runs everything. A change no rule reads updates the status line only.
|
|
37
|
+
- Only the rules whose directive or inputs changed are re-executed. On this
|
|
38
|
+
repository a save in `src` re-executes 21 of 60 rules in a median of 21 ms -
|
|
39
|
+
over the 15 ms it was built to, as ADR-0014 reports - and a save elsewhere
|
|
40
|
+
takes 2-3 ms.
|
|
41
|
+
- One recursive `fs.watch` on the root, and no dependency.
|
|
42
|
+
- Refuses `--engine` - it scans in-process, where it sees what each rule reads -
|
|
43
|
+
and `--json`, `--format json|sarif`, `--print-baseline`, `--fail-fast` and
|
|
44
|
+
`--allow-empty`.
|
|
45
|
+
- A test changes trees at random and requires every report a session gives to
|
|
46
|
+
equal a fresh run's, however the change is reported, and six deliberately
|
|
47
|
+
broken sessions have to fail it.
|
|
48
|
+
- **One door for every read** (`Io`, `nodeIo`, `readText`, `watchTree`), and the
|
|
49
|
+
session behind watch mode (`createSession`, `runWatch`, `createFactCache`,
|
|
50
|
+
`createMemo`) in the programmatic API. `runSpecGuard` is `planRun`, an
|
|
51
|
+
execution and `reportRun`, and those two are exported.
|
|
52
|
+
`createJavaScriptEngine(io, memo)` builds a scanner over a door, and
|
|
53
|
+
`createCachedEngine(engine, fallback)` names what it falls back to.
|
|
54
|
+
- `scripts/bench-watch.mjs`, which measures a session on a copy of this
|
|
55
|
+
repository.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- **API:** `defaultDirectoryReader` and `statOrNull` are gone for `nodeIo`.
|
|
60
|
+
`WalkOptions.readDirectory` is `WalkOptions.io`, `enumerateCandidates` takes an
|
|
61
|
+
`Io` as its third argument, and `createTreeIndex(root, io)` takes a whole door.
|
|
62
|
+
`Assertion.missingTargets` is gone: only execution ever wrote to it.
|
|
63
|
+
- This repository keeps its specs in `package.json`, and its selfcheck, CI run
|
|
64
|
+
and SARIF upload run `spec-guard` without patterns.
|
|
65
|
+
- **Mutation testing in CI runs in four parallel shards.** The full sweep took
|
|
66
|
+
42m39s against a 45-minute job limit, and a slower runner was cancelled on the
|
|
67
|
+
same source. Hosted runners vary by a fifth or more on identical work.
|
|
68
|
+
- Each shard mutates its own files, balanced on per-file minutes read from
|
|
69
|
+
sweep logs (`scripts/mutation-timeline.mjs`).
|
|
70
|
+
- A final job merges the reports (`scripts/mutation-shards.mjs`). It refuses a
|
|
71
|
+
missing shard, a file mutated twice or by the wrong shard, and shards that ran
|
|
72
|
+
different tests, then applies the 97% gate to the merged score.
|
|
73
|
+
- Every shard runs every test: Stryker's vitest runner now has `related: false`.
|
|
74
|
+
- A full sweep starts from no incremental file, and a branch's shard from only
|
|
75
|
+
its own part of main's. Stryker reports the verdicts an incremental file holds
|
|
76
|
+
for files a run does not mutate, and on the first sharded sweep every shard
|
|
77
|
+
reported every other shard's files with the previous sweep's verdicts. The
|
|
78
|
+
merge refused that sweep.
|
|
79
|
+
- No mutants were left out, the per-mutant timeout is unchanged, and the gate
|
|
80
|
+
is unchanged. [ADR-0003](docs/adr/0003-mutation-testing.md).
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- **A binary file was a gap for every rule sharing its pass.** A plain run scans
|
|
85
|
+
every rule over one scope together, and kept one ledger for them: a binary file
|
|
86
|
+
holding one rule's symbol was reported against all of them with their matches
|
|
87
|
+
summed, so `--strict` failed rules over files that did not hold their symbol.
|
|
88
|
+
The count of files whose comments could not be classified leaked the same way.
|
|
89
|
+
Each rule now has its own.
|
|
90
|
+
- **Two runs of one tree could list skipped files in different orders**, and past
|
|
91
|
+
the ledger's cap of 100, name different ones: files entered the ledger as their
|
|
92
|
+
reads finished. They now enter in walk order.
|
|
93
|
+
- Executing one resolved assertion twice named each missing target twice. Nothing
|
|
94
|
+
did so before watch mode.
|
|
95
|
+
- A test of the MCP server's durations that failed about one run in 53, on
|
|
96
|
+
floating-point error in the test.
|
|
97
|
+
|
|
98
|
+
## 0.8.0
|
|
99
|
+
|
|
100
|
+
An architecture document can now state conventions about names and layout: what
|
|
101
|
+
the files in a directory are called, what every package holds, and which files
|
|
102
|
+
come in pairs. [ADR-0013](docs/adr/0013-structure-assertions.md).
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
|
|
106
|
+
- **`@assert-structure`**, with exactly one of three claims per directive:
|
|
107
|
+
- `pattern="*.entity.ts, index.ts"` - every file in scope is named by one of
|
|
108
|
+
the patterns;
|
|
109
|
+
- `required="package.json, README.md"` - every directory holds each entry.
|
|
110
|
+
The directories are the targets, or with `dirs="*"` their children and with
|
|
111
|
+
`dirs="**"` every directory below them, empty ones included. An entry may be
|
|
112
|
+
a path, may end in a glob, and must be a directory when it ends in `/`;
|
|
113
|
+
- `partner="[name].test.[ext], tests/[dir]/test_[name].py"` - every file has
|
|
114
|
+
one of its partners. Three placeholders and no other grammar: `[name]` and
|
|
115
|
+
`[ext]` split the file name at its last dot, and `[dir]` is the file's
|
|
116
|
+
directory below its target.
|
|
117
|
+
|
|
118
|
+
Names are compared exactly from directory listings, never by looking a path
|
|
119
|
+
up, so `Readme.md` does not satisfy `README.md` on Windows or macOS any more
|
|
120
|
+
than it does on Linux. A scope with no files or no directories fails, as does
|
|
121
|
+
a partner template naming the file itself and a `required` target that is a
|
|
122
|
+
file. When a file has no partner because it *is* one, the report says so and
|
|
123
|
+
suggests the `exclude`. Takes `glob`, `exclude`, `max`, `allow-empty`,
|
|
124
|
+
`baseline` and `ratchet`. Spec files are in scope, and symbolic links are not
|
|
125
|
+
followed. All structure rules in a run share one walk per target and read
|
|
126
|
+
each directory once.
|
|
127
|
+
- `spec-guard query` and the MCP server show what a structure rule asks of a
|
|
128
|
+
path: whether a file's name is allowed, the partners it needs, and - for a
|
|
129
|
+
file in a directory a `required` rule holds - that rule.
|
|
130
|
+
- The JSON report carries `claim` on structure results. A match with `line: 0`
|
|
131
|
+
is a path rather than a place in one, and SARIF annotates a misnamed or
|
|
132
|
+
partnerless file at its first line, and a directory missing an entry at the
|
|
133
|
+
directive, with the directory in the message.
|
|
134
|
+
- `checkStructure`, `createTreeIndex`, `expandPartner`, `partnerTemplateIssue`
|
|
135
|
+
and `requiredEntryIssue` are exported, with their types. `walkPaths` takes an
|
|
136
|
+
`onDirectory` callback.
|
|
137
|
+
|
|
138
|
+
### Changed
|
|
139
|
+
|
|
140
|
+
- **`executeAssertion` needs a `tree`** in its options: `createTreeIndex(root)`,
|
|
141
|
+
the run's directory listings, beside the `imports` and `hasFiles` caches it
|
|
142
|
+
already takes. Only code calling `executeAssertion` directly is affected;
|
|
143
|
+
`runSpecGuard` and the command line create it themselves.
|
|
144
|
+
- The MCP server's instructions and the `get_architectural_rules` description
|
|
145
|
+
tell an agent that the rules for a path now include what it must be named and
|
|
146
|
+
the partner files it needs.
|
|
147
|
+
- **Mutation score 98.63%** over 6,939 mutants, up from 0.7.0's 98.47%, with 92
|
|
148
|
+
survivors - one fewer than before the 676 mutants this release adds.
|
|
149
|
+
`structure.ts` is at 100%, and every other module has exactly the survivors it
|
|
150
|
+
had, less one in `glob.ts` that the new tests turned into a genuine hang. A
|
|
151
|
+
local sweep had reported four survivors in the new listing cache as killed; CI
|
|
152
|
+
found them, and they are tested. See
|
|
153
|
+
[ADR-0003](docs/adr/0003-mutation-testing.md).
|
|
154
|
+
|
|
8
155
|
## 0.7.0
|
|
9
156
|
|
|
10
157
|
Two things an architecture document could not do before. It can state the shape
|
package/README.md
CHANGED
|
@@ -422,6 +422,99 @@ reading `tsconfig.json`, which is the resolver
|
|
|
422
422
|
[ADR-0011](docs/adr/0011-layers-and-cycles.md) declines to become, for the
|
|
423
423
|
reasons it gives.
|
|
424
424
|
|
|
425
|
+
### `@assert-structure` - what files are called, and what comes with them
|
|
426
|
+
|
|
427
|
+
Architecture documents state conventions over sets of files rather than naming
|
|
428
|
+
files one by one. Each directive makes exactly one of three claims:
|
|
429
|
+
|
|
430
|
+
```md
|
|
431
|
+
<!-- @assert-structure target="src/domain" exclude="*.test.ts" pattern="*.entity.ts, index.ts" -->
|
|
432
|
+
<!-- @assert-structure target="packages" dirs="*" required="package.json, README.md" -->
|
|
433
|
+
<!-- @assert-structure target="src/handlers" exclude="*.test.ts" partner="[name].test.ts" -->
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
- **`pattern`** - every file in scope is named by one of the patterns. They are
|
|
437
|
+
globs, read like `glob=`: without a `/` against the file name, with one
|
|
438
|
+
against the path from the root.
|
|
439
|
+
- **`required`** - every directory holds every entry. Without `dirs` the
|
|
440
|
+
directories are the targets; `dirs="*"` means their immediate children and
|
|
441
|
+
`dirs="**"` every directory below them. An entry may be a path
|
|
442
|
+
(`src/index.ts`), may end in a glob (`*.csproj`), and must be a directory
|
|
443
|
+
when it ends in `/`.
|
|
444
|
+
- **`partner`** - every file has a partner, named by a template.
|
|
445
|
+
|
|
446
|
+
Each failure names the file or directory, since there is no line to point at:
|
|
447
|
+
|
|
448
|
+
```text
|
|
449
|
+
✖ docs/architecture.md:3 @assert-structure
|
|
450
|
+
files in src/domain must be named *.entity.ts or index.ts (excluding *.test.ts)
|
|
451
|
+
expected no misnamed files, found 1
|
|
452
|
+
src/domain/helpers.ts matches none of *.entity.ts, index.ts
|
|
453
|
+
|
|
454
|
+
✖ docs/architecture.md:4 @assert-structure
|
|
455
|
+
directories matching * under packages must contain package.json, README.md
|
|
456
|
+
expected no directories missing an entry, found 2
|
|
457
|
+
packages/billing missing README.md
|
|
458
|
+
packages/web missing package.json, README.md
|
|
459
|
+
|
|
460
|
+
✖ docs/architecture.md:5 @assert-structure
|
|
461
|
+
files in src/handlers must each have a partner [name].test.ts (excluding *.test.ts)
|
|
462
|
+
expected no files without a partner, found 1
|
|
463
|
+
src/handlers/refund.ts has no partner src/handlers/refund.test.ts
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
A partner template has three placeholders and nothing else - no regular
|
|
467
|
+
expressions, no conditionals - so a reader can expand one by eye:
|
|
468
|
+
|
|
469
|
+
| Placeholder | For `src/api/user.handler.ts`, `target="src"` |
|
|
470
|
+
| --- | --- |
|
|
471
|
+
| `[name]` | `user.handler` - the file name up to its last dot |
|
|
472
|
+
| `[ext]` | `ts` - what follows that dot |
|
|
473
|
+
| `[dir]` | `api` - the file's directory below the target, empty at the top |
|
|
474
|
+
|
|
475
|
+
A template without a `/` names a file beside it. One with a `/` is a path from
|
|
476
|
+
the root, which is how a mirrored test tree is written:
|
|
477
|
+
`partner="tests/[dir]/test_[name].py"`. A comma-separated list gives
|
|
478
|
+
alternatives, any one of which will do.
|
|
479
|
+
|
|
480
|
+
The partners themselves are in scope unless `exclude` says otherwise. Forgetting
|
|
481
|
+
to exclude them is loud rather than silent, and says what probably happened:
|
|
482
|
+
|
|
483
|
+
```text
|
|
484
|
+
src/handlers/order.test.ts has no partner src/handlers/order.test.test.ts (it is the partner of src/handlers/order.ts - exclude it?)
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
Some things fail rather than pass, because each is a rule that would otherwise
|
|
488
|
+
check nothing:
|
|
489
|
+
- a scope holding no files, or selecting no directories (`allow-empty` as
|
|
490
|
+
everywhere else);
|
|
491
|
+
- a template that names the file itself (`partner="[name].[ext]"`);
|
|
492
|
+
- a `required` target that is a file.
|
|
493
|
+
|
|
494
|
+
**Names are compared exactly, on every platform.** Whether `README.md` exists is
|
|
495
|
+
decided by reading its directory, never by asking the filesystem for the path.
|
|
496
|
+
That lookup finds `Readme.md` on Windows and macOS and does not find it on Linux,
|
|
497
|
+
and the same rule would pass on a laptop and fail in CI.
|
|
498
|
+
|
|
499
|
+
A structure rule reads names, never contents. It walks with the run's usual
|
|
500
|
+
skips, follows no symbolic link, and counts the spec files - which every other
|
|
501
|
+
rule leaves out, and which a naming rule about `docs/adr` is about. `max`,
|
|
502
|
+
`baseline` and `ratchet` work as they do on `@assert-absence`, and a baseline
|
|
503
|
+
lists files or directories. `spec-guard query` shows what a rule asks of a file
|
|
504
|
+
that does not exist yet:
|
|
505
|
+
|
|
506
|
+
```text
|
|
507
|
+
src/handlers/invoice.ts (does not exist yet)
|
|
508
|
+
1 rule from 1 document
|
|
509
|
+
|
|
510
|
+
Architecture (docs/architecture.md)
|
|
511
|
+
:5 @assert-structure files in src/handlers must each have a partner [name].test.ts (excluding *.test.ts)
|
|
512
|
+
partner: src/handlers/invoice.test.ts
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
[ADR-0013](docs/adr/0013-structure-assertions.md) has the design and what it
|
|
516
|
+
costs.
|
|
517
|
+
|
|
425
518
|
### `@assert-present` - this file exists
|
|
426
519
|
|
|
427
520
|
```md
|
|
@@ -435,23 +528,27 @@ Passes when every listed path exists relative to `--root`. Directories count.
|
|
|
435
528
|
|
|
436
529
|
| Attribute | Applies to | Meaning |
|
|
437
530
|
| --- | --- | --- |
|
|
438
|
-
| `target` |
|
|
531
|
+
| `target` | all but present | Comma-separated paths, relative to `--root`. Default `.` |
|
|
439
532
|
| `symbol` | absence, count | The literal string to search for (or a regex with `regex="true"`) |
|
|
440
533
|
| `file` | present | Comma-separated paths that must exist |
|
|
441
|
-
| `expected` |
|
|
442
|
-
| `min` / `max` | count (`max`
|
|
443
|
-
| `glob` | absence, count | Include-only file filters, e.g. `*.ts,*.tsx` (ripgrep `-g` semantics) |
|
|
444
|
-
| `exclude` |
|
|
534
|
+
| `expected` | all but present | Exact count for count; an upper bound everywhere else |
|
|
535
|
+
| `min` / `max` | count (`max` on all but present) | Inclusive bounds |
|
|
536
|
+
| `glob` | absence, count, structure | Include-only file filters, e.g. `*.ts,*.tsx` (ripgrep `-g` semantics) |
|
|
537
|
+
| `exclude` | all but present | Paths to leave out, gitignore-style: `src/config/**`, `tests`, `*.test.ts` |
|
|
445
538
|
| `regex` | absence, count | Treat `symbol` as a regular expression |
|
|
446
539
|
| `word` | absence, count | Require word boundaries, so `Primary` does not match `PrimaryButton` |
|
|
447
540
|
| `ignore-case` | absence, count | Case-insensitive matching |
|
|
448
541
|
| `comments` | absence, count | `ignore` (default) or `include` for matches inside comments |
|
|
449
542
|
| `module` | import-absence, import-count | Which dependency, matched like `exclude` |
|
|
450
543
|
| `order` | layers | The layers, from the one everything may depend on to the one that may depend on everything |
|
|
544
|
+
| `pattern` | structure | The names every file in scope must match one of |
|
|
545
|
+
| `required` | structure | The entries every chosen directory must hold; a trailing `/` means a directory |
|
|
546
|
+
| `dirs` | structure, with `required` | Which directories below each target: `*` for children, `**` for all |
|
|
547
|
+
| `partner` | structure | Partner templates, any one of which must exist: `[name].test.[ext]` |
|
|
451
548
|
| `types` | import assertions, layers, cycles | `include` (default) or `ignore` for `import type` |
|
|
452
|
-
| `allow-empty` |
|
|
453
|
-
| `baseline` | absence, import-absence, layers | Known violations that do not count: `path` or `path:count` |
|
|
454
|
-
| `ratchet` | absence, import-absence, layers | `two-sided` (default) or `one-way` - see below |
|
|
549
|
+
| `allow-empty` | all but present | Tolerate a scope that holds no files, a layer that matches none, or no chosen directories. Off by default - see below |
|
|
550
|
+
| `baseline` | absence, import-absence, layers, structure | Known violations that do not count: `path` or `path:count` |
|
|
551
|
+
| `ratchet` | absence, import-absence, layers, structure | `two-sided` (default) or `one-way` - see below |
|
|
455
552
|
| `reason` | all | Human-readable justification, printed on failure |
|
|
456
553
|
|
|
457
554
|
Unknown attributes are an error, not a shrug: `expct="1"` fails the run instead
|
|
@@ -661,6 +758,7 @@ sources they follow, and what is deliberately not implemented.
|
|
|
661
758
|
|
|
662
759
|
```bash
|
|
663
760
|
spec-guard [patterns...] [options] # execute the directives
|
|
761
|
+
spec-guard --watch [patterns...] # execute them again whenever the tree changes
|
|
664
762
|
spec-guard query <paths...> [options] # the rules in force for files or directories
|
|
665
763
|
spec-guard mcp [options] # serve the rules over MCP on stdio
|
|
666
764
|
```
|
|
@@ -670,17 +768,18 @@ spec-guard mcp [options] # serve the rules over MCP on stdio
|
|
|
670
768
|
| `-r, --root <path>` | Codebase root that assertions resolve against (default: cwd) |
|
|
671
769
|
| `--spec <pattern>` | A spec glob or path, repeatable. `query` and `mcp` take their specs only from here |
|
|
672
770
|
| `-v, --verbose` | Print passing assertions too |
|
|
771
|
+
| `--watch` | Report, then report again as the tree changes, until Ctrl+C |
|
|
673
772
|
| `--fail-fast` | Stop at the first failing assertion |
|
|
674
773
|
| `--json` | Machine-readable report on stdout (same as `--format json`) |
|
|
675
774
|
| `--format <human\|json\|sarif>` | Output format. `sarif` uploads to GitHub code scanning |
|
|
676
775
|
| `--engine <auto\|rg\|js>` | Search engine (default `auto`: scanner for small trees, ripgrep for big ones) |
|
|
677
|
-
| `--strict` | Treat analysis that could not be completed as a failure |
|
|
678
|
-
| `--allow-missing-targets` | Warn instead of failing when a `target` path does not exist |
|
|
679
|
-
| `--allow-empty-scope` | Warn instead of failing when an assertion inspects no files |
|
|
776
|
+
| `--strict` / `--no-strict` | Treat analysis that could not be completed as a failure |
|
|
777
|
+
| `--allow-missing-targets` / `--no-allow-missing-targets` | Warn instead of failing when a `target` path does not exist |
|
|
778
|
+
| `--allow-empty-scope` / `--no-allow-empty-scope` | Warn instead of failing when an assertion inspects no files |
|
|
680
779
|
| `--print-baseline` | Print the `baseline="..."` that would exempt today's violations, and exit |
|
|
681
|
-
| `--no-default-skips` | Search `.git`, `.hg`, `.svn` and `node_modules` too |
|
|
682
|
-
| `--ignore-status` | Execute directives in draft, proposed and superseded documents too |
|
|
683
|
-
| `--include-specs` | Also count matches inside the spec files themselves |
|
|
780
|
+
| `--no-default-skips` / `--default-skips` | Search `.git`, `.hg`, `.svn` and `node_modules` too |
|
|
781
|
+
| `--ignore-status` / `--no-ignore-status` | Execute directives in draft, proposed and superseded documents too |
|
|
782
|
+
| `--include-specs` / `--no-include-specs` | Also count matches inside the spec files themselves |
|
|
684
783
|
| `--max-snippets <n>` | Failure snippets per assertion (default 5) |
|
|
685
784
|
| `--concurrency <n>` | Search passes in flight at once (default 8) |
|
|
686
785
|
| `--allow-empty` | Exit 0 when no spec file matched the patterns (about the run, not an assertion) |
|
|
@@ -688,6 +787,93 @@ spec-guard mcp [options] # serve the rules over MCP on stdio
|
|
|
688
787
|
|
|
689
788
|
Patterns are expanded by spec-guard itself, so quoted globs behave identically
|
|
690
789
|
on Windows, macOS and Linux. A directory expands to the Markdown files in it.
|
|
790
|
+
The second form of each on/off option exists to override a configuration.
|
|
791
|
+
|
|
792
|
+
### Configuration
|
|
793
|
+
|
|
794
|
+
The options that are a project's policy can live in `package.json`, under
|
|
795
|
+
`"specGuard"`, so CI, a pre-commit hook and the MCP server an agent starts all
|
|
796
|
+
hold the same rules the same way:
|
|
797
|
+
|
|
798
|
+
```json
|
|
799
|
+
{
|
|
800
|
+
"specGuard": {
|
|
801
|
+
"specs": ["docs/**/*.md", "README.md"],
|
|
802
|
+
"strict": true
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
| Key | Command line | Value |
|
|
808
|
+
| --- | --- | --- |
|
|
809
|
+
| `specs` | patterns, `--spec` | a non-empty array of globs |
|
|
810
|
+
| `engine` | `--engine` | `"auto"`, `"rg"` or `"js"` |
|
|
811
|
+
| `strict`, `allowMissingTargets`, `allowEmptyScope`, `ignoreStatus`, `includeSpecs`, `defaultSkips` | the flag of that name | `true` or `false` |
|
|
812
|
+
| `maxSnippets` | `--max-snippets` | an integer, 0 or more |
|
|
813
|
+
| `concurrency` | `--concurrency` | an integer, 1 or more |
|
|
814
|
+
|
|
815
|
+
- **Only the root's `package.json`** is read: the `--root` directory, or the
|
|
816
|
+
working directory. Nothing is inherited from a parent directory.
|
|
817
|
+
- **The command line wins, both ways.** Patterns replace `specs`, and
|
|
818
|
+
`--no-strict` beats `"strict": true`.
|
|
819
|
+
- **A malformed configuration is exit 2, before anything runs**, naming the file
|
|
820
|
+
and the key: an unknown key, `"true"` where `true` goes, or an option that
|
|
821
|
+
belongs to one invocation, such as `format` or `verbose`.
|
|
822
|
+
- **Every report says what it took from the file**: a line above the summary
|
|
823
|
+
such as `options from package.json: specs, strict`, and a `config` field in
|
|
824
|
+
JSON. An
|
|
825
|
+
option nobody can see should never decide a result.
|
|
826
|
+
- `query` applies what a query reads, and the MCP server reads the file again
|
|
827
|
+
for every request.
|
|
828
|
+
|
|
829
|
+
### Watch mode
|
|
830
|
+
|
|
831
|
+
```bash
|
|
832
|
+
spec-guard --watch
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
Prints the report, then prints it again whenever something under the root
|
|
836
|
+
changes, until Ctrl+C. Saves are batched: a batch starts after 50 ms without a
|
|
837
|
+
new change, or 500 ms after its first. On a terminal the screen is redrawn;
|
|
838
|
+
otherwise each report is appended under the time. A change that no rule reads
|
|
839
|
+
updates the status line and nothing else:
|
|
840
|
+
|
|
841
|
+
```text
|
|
842
|
+
watching 15 specs · 1 change · 21 of 60 rules re-executed · 21 ms · Enter re-runs everything, Ctrl+C stops
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
A session re-executes only the rules whose directive or inputs changed. Every
|
|
846
|
+
filesystem read goes through one module, so the session can record which rule
|
|
847
|
+
read what. A watcher's event only evicts what it may have changed, and the
|
|
848
|
+
evicted facts are read again and compared, so noise costs one directory read,
|
|
849
|
+
and a renamed directory's contents need no events of their own. Work that is a
|
|
850
|
+
pure function of a file's bytes - tokenizing, comment masking, scanning - is
|
|
851
|
+
remembered by the bytes' hash. Each of those is a way to report a tree that no
|
|
852
|
+
longer exists, so a test changes trees at random and requires every report a
|
|
853
|
+
session gives to equal a fresh run's, with six deliberately broken sessions
|
|
854
|
+
that it has to catch. [ADR-0014](docs/adr/0014-configuration-and-watch.md) has
|
|
855
|
+
the design, the measurements and the limits.
|
|
856
|
+
|
|
857
|
+
On this repository, from a change to the report, in the quietest of four runs
|
|
858
|
+
(a plain warm run took 69 ms in it):
|
|
859
|
+
|
|
860
|
+
| Edit | Rules re-executed | Median |
|
|
861
|
+
| --- | --- | --- |
|
|
862
|
+
| a file in `src` | 21 of 60 | 21 ms |
|
|
863
|
+
| a test file | 1 of 60 | 3.3 ms |
|
|
864
|
+
| a file no rule reads | 0 | 2.0 ms |
|
|
865
|
+
| an ADR's prose | 0 | 2.4 ms |
|
|
866
|
+
|
|
867
|
+
The 15 ms this was built to is missed for a save in `src`, which re-executes the
|
|
868
|
+
two layer rules and every text rule over `src`; ADR-0014 says where the time
|
|
869
|
+
goes.
|
|
870
|
+
|
|
871
|
+
`--watch` scans in-process, where it can see what each rule reads, so it refuses
|
|
872
|
+
`--engine`, and `--json`, `--format json|sarif`, `--print-baseline`,
|
|
873
|
+
`--fail-fast` and `--allow-empty`, which each describe a single run. It exits
|
|
874
|
+
130 when stopped, since a session is neither a pass nor a failure. What it
|
|
875
|
+
cannot see: a change the operating system never reports, a change behind a
|
|
876
|
+
symbolic link, and anything outside the root. CI stays the authority.
|
|
691
877
|
|
|
692
878
|
### Exit codes
|
|
693
879
|
|
|
@@ -695,7 +881,8 @@ on Windows, macOS and Linux. A directory expands to the Markdown files in it.
|
|
|
695
881
|
| --- | --- |
|
|
696
882
|
| `0` | Every assertion held |
|
|
697
883
|
| `1` | An assertion failed, or a directive was malformed |
|
|
698
|
-
| `2` | spec-guard could not run: bad usage, no spec files matched, `--engine rg` with no ripgrep |
|
|
884
|
+
| `2` | spec-guard could not run: bad usage, a malformed configuration, no spec files matched, `--engine rg` with no ripgrep, a watch that could not start |
|
|
885
|
+
| `130` | A `--watch` session was stopped |
|
|
699
886
|
|
|
700
887
|
## CI integration
|
|
701
888
|
|
|
@@ -757,9 +944,10 @@ spec-guard's claims are about a whole repository - "this symbol appears nowhere
|
|
|
757
944
|
in `src`" - and a language server is handed one buffer at a time. Answering a
|
|
758
945
|
repository-wide question on every keystroke means rescanning the tree on every
|
|
759
946
|
keystroke; the alternative is answering a smaller question and calling it the
|
|
760
|
-
same one.
|
|
761
|
-
|
|
762
|
-
daemon, an extension per editor, or a protocol
|
|
947
|
+
same one. `--watch` re-evaluates this repository in milliseconds after a save
|
|
948
|
+
by re-executing only what the save affected, and a pre-commit hook closes the
|
|
949
|
+
rest of the gap, without a daemon, an extension per editor, or a protocol
|
|
950
|
+
version matrix.
|
|
763
951
|
|
|
764
952
|
## How it works
|
|
765
953
|
|
|
@@ -1002,7 +1190,7 @@ npm install
|
|
|
1002
1190
|
npm run build # tsc -> dist/
|
|
1003
1191
|
npm test # vitest
|
|
1004
1192
|
npm run test:coverage
|
|
1005
|
-
npm run test:mutation # stryker (
|
|
1193
|
+
npm run test:mutation # stryker (four parallel jobs in CI; hours locally)
|
|
1006
1194
|
npm run lint # tsc --noEmit
|
|
1007
1195
|
npm run selfcheck # run spec-guard on its own docs
|
|
1008
1196
|
```
|
|
@@ -1017,10 +1205,13 @@ prebuilt binary and is never a runtime dependency.
|
|
|
1017
1205
|
|
|
1018
1206
|
Coverage says a line ran. It does not say an assertion would notice if the line
|
|
1019
1207
|
behaved differently. This repository measures the difference: line coverage is
|
|
1020
|
-
**100%**, and **
|
|
1021
|
-
95%. The second number is the one worth reading
|
|
1022
|
-
|
|
1023
|
-
|
|
1208
|
+
**100%**, and **98.84%** of 7,763 mutants are killed in CI, with 87 survivors and
|
|
1209
|
+
no file below 95%. The second number is the one worth reading, and what was done
|
|
1210
|
+
about the survivors matters more than the score. At 0.5.1 every surviving mutant
|
|
1211
|
+
was checked individually, and the 101 left then produced byte-identical output.
|
|
1212
|
+
Each release since has replayed the survivors its own code added before it
|
|
1213
|
+
shipped: they were killed, deleted as dead code, or shown equivalent and
|
|
1214
|
+
recorded in [ADR-0003](docs/adr/0003-mutation-testing.md) with the evidence.
|
|
1024
1215
|
|
|
1025
1216
|
That gap is the point. The first run scored 77.23%, and the weakest file was the
|
|
1026
1217
|
reporter at 65.48% - not because it lacked tests, but because its tests were
|
|
@@ -1061,13 +1252,19 @@ quoted above; a full sweep is also what publishes the cache the branches start
|
|
|
1061
1252
|
from, so an incremental verdict can never be built on another incremental
|
|
1062
1253
|
verdict.
|
|
1063
1254
|
|
|
1064
|
-
The full sweep was 6m54s at 2,118 mutants, 15m51s at 3,493, and
|
|
1065
|
-
|
|
1066
|
-
|
|
1255
|
+
The full sweep was 6m54s at 2,118 mutants, 15m51s at 3,493, and 42m39s at 7,763.
|
|
1256
|
+
That growth is why the tiers exist: a check that gets quietly more expensive
|
|
1257
|
+
every release is a check somebody eventually proposes lowering. It is also why
|
|
1258
|
+
both tiers now run in four parallel shards. One runner
|
|
1259
|
+
could no longer finish the full sweep reliably inside the job's limit, and the
|
|
1260
|
+
answer was to split the sweep rather than raise the limit or drop mutants.
|
|
1261
|
+
Each shard mutates its own files against every test, and a final job merges the
|
|
1262
|
+
reports. The merge refuses anything that is not exactly one sweep, and applies
|
|
1263
|
+
the 97% gate to the merged score with the same library Stryker's gate uses.
|
|
1067
1264
|
|
|
1068
1265
|
Run it locally with `npm run test:mutation` if you like, but do not calibrate
|
|
1069
1266
|
anything on the result: on the Windows machine this was developed on the same
|
|
1070
|
-
suite takes
|
|
1267
|
+
suite takes hours against 43 minutes of hosted time, and it scores *higher*,
|
|
1071
1268
|
because far more mutants hang there and Stryker counts a hang as a kill. Linux
|
|
1072
1269
|
CI is the measurement.
|
|
1073
1270
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
* 2 - spec-guard could not run (bad usage, no spec files, missing engine)
|
|
8
8
|
*/
|
|
9
9
|
import type { Readable } from 'node:stream';
|
|
10
|
+
import { type ConfigKey, type ProjectConfig } from './config.js';
|
|
11
|
+
import { watchTree } from './io.js';
|
|
10
12
|
import type { EnginePreference } from './engine.js';
|
|
13
|
+
import type { ConfigUse } from './types.js';
|
|
11
14
|
export declare const EXIT_OK = 0;
|
|
12
15
|
export declare const EXIT_FAILED = 1;
|
|
13
16
|
export declare const EXIT_ERROR = 2;
|
|
@@ -17,8 +20,17 @@ export interface CliIO {
|
|
|
17
20
|
env: NodeJS.ProcessEnv;
|
|
18
21
|
cwd: string;
|
|
19
22
|
isTTY: boolean;
|
|
20
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Where `spec-guard mcp` reads its messages, and where a watch session hears
|
|
25
|
+
* Enter. Nothing else reads input.
|
|
26
|
+
*/
|
|
21
27
|
stdin?: Readable;
|
|
28
|
+
/** Writes to stdout as it is, with no newline added: a watch session redraws. */
|
|
29
|
+
write?: (text: string) => void;
|
|
30
|
+
/** Starts a recursive watch on a directory; a test passes one it drives itself. */
|
|
31
|
+
watch?: typeof watchTree;
|
|
32
|
+
/** Registers what Ctrl+C and SIGTERM do, and returns how to unregister it. */
|
|
33
|
+
onInterrupt?: (handler: () => void) => () => void;
|
|
22
34
|
}
|
|
23
35
|
/** What the command line asked for: a run, a query, or a server. */
|
|
24
36
|
export type Command = 'check' | 'query' | 'mcp';
|
|
@@ -47,8 +59,18 @@ export interface CliOptions {
|
|
|
47
59
|
maxSnippets: number;
|
|
48
60
|
concurrency: number;
|
|
49
61
|
color?: boolean;
|
|
62
|
+
/** Re-run as the tree changes, until stopped. ADR-0014. */
|
|
63
|
+
watch: boolean;
|
|
50
64
|
help: boolean;
|
|
51
65
|
version: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* The configurable options the command line set, either way.
|
|
68
|
+
*
|
|
69
|
+
* A configuration fills in only what is not here, so a flag always wins - and
|
|
70
|
+
* `--strict` given alongside `"strict": true` is still reported as the command
|
|
71
|
+
* line's doing, not the file's.
|
|
72
|
+
*/
|
|
73
|
+
fromCommandLine: Set<ConfigKey>;
|
|
52
74
|
}
|
|
53
75
|
export declare class UsageError extends Error {
|
|
54
76
|
}
|
|
@@ -60,9 +82,22 @@ export declare class UsageError extends Error {
|
|
|
60
82
|
* fallback nobody knows still works.
|
|
61
83
|
*/
|
|
62
84
|
export declare function version(manifest?: string): string;
|
|
63
|
-
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\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 and\n mcp 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 --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 (sarif uploads to GitHub code scanning)\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 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 --ignore-status Execute directives in draft, proposed and superseded documents too\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 --allow-empty Exit 0 when no spec files matched (about the run, not an assertion)\n --color/--no-color Force colour on or off (NO_COLOR is honoured)\n -h, --help Show this help\n --version Print the version\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\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 or superseded\n is reported and not executed; --ignore-status runs it anyway.\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, and a check,\nas the tools get_architectural_rules and check_architecture.\n\nExit codes\n 0 all assertions passed 1 an assertion failed 2 spec-guard could not run";
|
|
85
|
+
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\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 and\n mcp 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 (sarif uploads to GitHub code scanning)\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 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 --ignore-status Execute directives in draft, proposed and superseded documents too\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 --allow-empty Exit 0 when no spec files matched (about the run, not an assertion)\n --color/--no-color Force colour on or off (NO_COLOR is honoured)\n -h, --help Show this help\n --version Print the version\n\nConfiguration\n package.json in the root can hold specs, engine, strict, allowMissingTargets,\n allowEmptyScope, ignoreStatus, includeSpecs, defaultSkips, maxSnippets and\n concurrency under \"specGuard\". A flag wins over the file, and every on/off\n option there also takes its opposite (--no-strict, --default-skips, ...).\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 or superseded\n is reported and not executed; --ignore-status runs it anyway.\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, and a check,\nas the tools get_architectural_rules and check_architecture.\n\nExit codes\n 0 all assertions passed 1 an assertion failed 2 spec-guard could not run\n 130 a --watch session was stopped";
|
|
64
86
|
/** Minimal, dependency-free argv parser. Supports `--flag value` and `--flag=value`. */
|
|
65
87
|
export declare function parseArgs(argv: readonly string[], cwd: string): CliOptions;
|
|
88
|
+
/**
|
|
89
|
+
* Fills in what the command line left unset from a configuration, and says what
|
|
90
|
+
* it took.
|
|
91
|
+
*
|
|
92
|
+
* A key the command does not read is neither applied nor overridden: `strict`
|
|
93
|
+
* is written for the runs, and a query that ignores it has not been told
|
|
94
|
+
* anything about strictness. A watch session scans in-process, so `engine` is
|
|
95
|
+
* not one of its keys either. Returns nothing when the configuration had
|
|
96
|
+
* nothing to say to this command, so a report says nothing about it.
|
|
97
|
+
*/
|
|
98
|
+
export declare function applyConfig(options: CliOptions, config: ProjectConfig, file?: string): ConfigUse | undefined;
|
|
99
|
+
/** The process's own streams, signals and filesystem watcher. */
|
|
100
|
+
export declare function defaultIO(): CliIO;
|
|
66
101
|
/** Runs the CLI and resolves to the process exit code. */
|
|
67
102
|
export declare function main(argv?: readonly string[], io?: CliIO): Promise<number>;
|
|
68
103
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|