v11y-check 0.18.0 โ†’ 0.19.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.
@@ -1,4 +1,106 @@
1
1
  [
2
+ {
3
+ "version": "0.19.0",
4
+ "date": "2026-10-01",
5
+ "sections": [
6
+ {
7
+ "title": "๐ŸŽ‰ Features",
8
+ "audience": "all",
9
+ "items": [
10
+ {
11
+ "description": "Adds `v11y update-templates`, which writes `.github/workflows/audit.yaml` when it is missing or differs from the installed template, prints a diff of the update, and never reads or writes the config file. (#952)",
12
+ "hash": "9fac96675e9fb4dd70407cbfb0e3e0ffa7e83ba4",
13
+ "entry": 2
14
+ },
15
+ {
16
+ "description": "Changes the readyup kits' fix messages for a workflow that differs from its template, or that references a deprecated tag, to recommend `update-templates` rather than `init --force`. (#952)",
17
+ "hash": "9fac96675e9fb4dd70407cbfb0e3e0ffa7e83ba4",
18
+ "entry": 3
19
+ }
20
+ ]
21
+ },
22
+ {
23
+ "title": "๐Ÿ› Bug fixes",
24
+ "audience": "all",
25
+ "items": [
26
+ {
27
+ "description": "Rewords the `v11y-check` README and the message that `v11y` prints for missing build output, which addressed the reader in the second person and used em-dashes and figurative verbs. (#939)",
28
+ "hash": "700bc1f5ef09a8e6167de0bf109940f26eb4c18e",
29
+ "entry": 1
30
+ },
31
+ {
32
+ "description": "Fixes the issue that two comments in the `audit.yaml` workflow generated by `v11y init` did not follow the project's writing rules; the v11y-check kit check reports a previously generated `audit.yaml` as stale until `v11y init --force` regenerates it. (#946)",
33
+ "hash": "dc1c4bd4b05425ed1c2a7d031105c402c3d01f20",
34
+ "entry": 2
35
+ }
36
+ ]
37
+ },
38
+ {
39
+ "title": "โ™ป๏ธ Refactoring",
40
+ "audience": "dev",
41
+ "items": [
42
+ {
43
+ "description": "Replaces every `.sort()` call that suppressed `unicorn/no-array-sort` with `toSorted()` and drops the spread copy wherever the source was already an array. (#925)",
44
+ "hash": "4680fb4e865ffce0bd135fac20d49b766b156992",
45
+ "entry": 1
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "title": "๐Ÿงช Tests",
51
+ "audience": "dev",
52
+ "items": [
53
+ {
54
+ "description": "Renames the `resolveAuditCiBin` test to `returns a non-empty path to the audit-ci bin`, because the old title claimed that it exercised the fallback, and moves a verbose-hint test from the \"Threshold annotation\" group to the \"Actions footer\" group of `format-check.unit.test.ts`. (#924)",
55
+ "hash": "71a216c8403245b45c42acd06c23ebad09063c1f",
56
+ "entry": 2
57
+ },
58
+ {
59
+ "description": "Moves the helpers in the `format-check`, `format-summary`, and `format-verbose` unit tests below their `describe` blocks and sorts them alphabetically, matching `cli.unit.test.ts` and `run-audit.unit.test.ts`. (#947)",
60
+ "hash": "a0b69c1fa72236e877d1b973140ad6ac40a91018",
61
+ "entry": 2
62
+ }
63
+ ]
64
+ },
65
+ {
66
+ "title": "๐Ÿ“ฆ Dependencies",
67
+ "audience": "dev",
68
+ "items": [
69
+ {
70
+ "description": "Adds `esbuild` 0.28.2 to the pnpm catalog and declares it as a devDependency of `nmr`, `release-kit`, and `v11y-check`, because `readyup` declares it only as an optional peer and `rdy compile` failed in those packages once a regenerated lockfile stopped installing it. (#944)",
71
+ "hash": "6dffd5df5bc4209dc225d08390ef2b67fe381f1b",
72
+ "entry": 2
73
+ }
74
+ ]
75
+ },
76
+ {
77
+ "title": "๐Ÿ“š Documentation",
78
+ "audience": "dev",
79
+ "items": [
80
+ {
81
+ "description": "Revises the comments in `packages/v11y-check/src` and the `default` readyup kit against the comment-discipline rules, correcting the ones that misstated the code, such as the `@internal Exported for testing` tags on functions that production code calls, and deleting the ones that restated it. (#924)",
82
+ "hash": "71a216c8403245b45c42acd06c23ebad09063c1f",
83
+ "entry": 1
84
+ },
85
+ {
86
+ "description": "Revises the doc comments, code comments, and test titles across `packages/v11y-check`, including its readyup kit, to follow the plain-speech doctrine and writing conventions. (#939)",
87
+ "hash": "700bc1f5ef09a8e6167de0bf109940f26eb4c18e",
88
+ "entry": 2
89
+ },
90
+ {
91
+ "description": "Replaces the inline headings of the `Types` and `Display ID helper` sections in `format-check.ts`, and of the `Helpers` sections in the `format-check`, `format-summary`, and `format-verbose` unit tests, with `// region | โ€ฆ` / `// endregion | โ€ฆ` folds, which the house style reserves for supporting blocks. (#947)",
92
+ "hash": "a0b69c1fa72236e877d1b973140ad6ac40a91018",
93
+ "entry": 1
94
+ },
95
+ {
96
+ "description": "Retitles the `Dependency updates` section of v11y-check's 0.14.1 changelog entry to `๐Ÿ“ฆ Dependencies`, in `.meta/changelog.json` and in the `CHANGELOG.md` rendered from it, so that the next release does not re-emit the retired title. (#950)",
97
+ "hash": "5a4771a1cb1e1b324a9ce3cb64fc3527199946a7",
98
+ "entry": 2
99
+ }
100
+ ]
101
+ }
102
+ ]
103
+ },
2
104
  {
3
105
  "version": "0.18.0",
4
106
  "date": "2026-09-18",
@@ -307,7 +409,7 @@
307
409
  "date": "2026-08-04",
308
410
  "sections": [
309
411
  {
310
- "title": "Dependency updates",
412
+ "title": "๐Ÿ“ฆ Dependencies",
311
413
  "audience": "dev",
312
414
  "items": [{ "description": "Bumped `@williamthorsen/nmr-core` to 0.9.1" }]
313
415
  }
@@ -8,13 +8,13 @@ import { existsSync } from "node:fs";
8
8
  import { join } from "node:path";
9
9
  import { defineRdyKit } from "readyup";
10
10
  import { fileExists, fileMatchesHash, hasDevDependency, hasMinDevDependencyVersion } from "readyup/check-utils";
11
- var AUDIT_WORKFLOW_HASH = "cdcab39d794ed7ec5ea45e8f3c887eb5d15edb63eab65e515714556933d9b03f";
11
+ var AUDIT_WORKFLOW_HASH = "ad969e3fefe603cee04de02e300e6f4d4d9dae9e8e58bddb9db81980115bc260";
12
12
  var default_default = defineRdyKit({
13
13
  checklists: [
14
14
  {
15
15
  name: "v11y-check",
16
16
  checks: [
17
- // -- Setup ---------------------------------------------------------------
17
+ // -- Setup --
18
18
  {
19
19
  name: "v11y-check in devDependencies",
20
20
  severity: "error",
@@ -35,7 +35,7 @@ var default_default = defineRdyKit({
35
35
  }
36
36
  ]
37
37
  },
38
- // -- Audit-ci config migration -------------------------------------------
38
+ // -- Audit-ci config migration --
39
39
  {
40
40
  name: "audit-ci configs are under .config/audit-ci/",
41
41
  severity: "warn",
@@ -43,7 +43,7 @@ var default_default = defineRdyKit({
43
43
  check: noLegacyAuditCiDirectory,
44
44
  fix: "Move audit-ci configs from .audit-ci/ to .config/audit-ci/ and update references"
45
45
  },
46
- // -- Audit workflow ------------------------------------------------------
46
+ // -- Audit workflow --
47
47
  {
48
48
  name: "audit.yaml workflow exists",
49
49
  severity: "warn",
@@ -54,7 +54,7 @@ var default_default = defineRdyKit({
54
54
  name: "audit.yaml matches template",
55
55
  severity: "warn",
56
56
  check: () => fileMatchesHash(".github/workflows/audit.yaml", AUDIT_WORKFLOW_HASH),
57
- fix: "Run `v11y init --force` to regenerate audit.yaml from the current template"
57
+ fix: "Run `v11y update-templates` to regenerate audit.yaml from the current template"
58
58
  }
59
59
  ]
60
60
  }
@@ -63,7 +63,7 @@ var default_default = defineRdyKit({
63
63
  ]
64
64
  });
65
65
  function getMinVersion() {
66
- const picked = { "version": "0.18.0" };
66
+ const picked = { "version": "0.19.0" };
67
67
  if (typeof picked["version"] !== "string") {
68
68
  throw new TypeError("v11y-check/package.json: 'version' must be a string");
69
69
  }
@@ -8,12 +8,12 @@
8
8
  "esbuildVersion": "0.28.2",
9
9
  "inputs": [
10
10
  {
11
- "hash": "5600fe16",
11
+ "hash": "3ca06efb",
12
12
  "kind": "module",
13
13
  "path": "kits/default.ts"
14
14
  },
15
15
  {
16
- "hash": "b9dec108",
16
+ "hash": "819284aa",
17
17
  "kind": "inline",
18
18
  "path": "../package.json",
19
19
  "paths": [
@@ -25,8 +25,8 @@
25
25
  "path": "kits/default.js",
26
26
  "readyupVersion": "0.38.0",
27
27
  "source": "kits/default.ts",
28
- "sourceHash": "5600fe16",
29
- "targetHash": "35553b19"
28
+ "sourceHash": "3ca06efb",
29
+ "targetHash": "32c10111"
30
30
  }
31
31
  ]
32
32
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.19.0 โ€” 2026-10-01
6
+
7
+ ### ๐ŸŽ‰ Features
8
+
9
+ - Adds `v11y update-templates`, which writes `.github/workflows/audit.yaml` when it is missing or differs from the installed template, prints a diff of the update, and never reads or writes the config file. (#952)
10
+ - Changes the readyup kits' fix messages for a workflow that differs from its template, or that references a deprecated tag, to recommend `update-templates` rather than `init --force`. (#952)
11
+
12
+ ### ๐Ÿ› Bug fixes
13
+
14
+ - Rewords the `v11y-check` README and the message that `v11y` prints for missing build output, which addressed the reader in the second person and used em-dashes and figurative verbs. (#939)
15
+ - Fixes the issue that two comments in the `audit.yaml` workflow generated by `v11y init` did not follow the project's writing rules; the v11y-check kit check reports a previously generated `audit.yaml` as stale until `v11y init --force` regenerates it. (#946)
16
+
17
+ ### โ™ป๏ธ Refactoring
18
+
19
+ - Replaces every `.sort()` call that suppressed `unicorn/no-array-sort` with `toSorted()` and drops the spread copy wherever the source was already an array. (#925)
20
+
21
+ ### ๐Ÿงช Tests
22
+
23
+ - Renames the `resolveAuditCiBin` test to `returns a non-empty path to the audit-ci bin`, because the old title claimed that it exercised the fallback, and moves a verbose-hint test from the "Threshold annotation" group to the "Actions footer" group of `format-check.unit.test.ts`. (#924)
24
+ - Moves the helpers in the `format-check`, `format-summary`, and `format-verbose` unit tests below their `describe` blocks and sorts them alphabetically, matching `cli.unit.test.ts` and `run-audit.unit.test.ts`. (#947)
25
+
26
+ ### ๐Ÿ“ฆ Dependencies
27
+
28
+ - Adds `esbuild` 0.28.2 to the pnpm catalog and declares it as a devDependency of `nmr`, `release-kit`, and `v11y-check`, because `readyup` declares it only as an optional peer and `rdy compile` failed in those packages once a regenerated lockfile stopped installing it. (#944)
29
+
30
+ ### ๐Ÿ“š Documentation
31
+
32
+ - Revises the comments in `packages/v11y-check/src` and the `default` readyup kit against the comment-discipline rules, correcting the ones that misstated the code, such as the `@internal Exported for testing` tags on functions that production code calls, and deleting the ones that restated it. (#924)
33
+ - Revises the doc comments, code comments, and test titles across `packages/v11y-check`, including its readyup kit, to follow the plain-speech doctrine and writing conventions. (#939)
34
+ - Replaces the inline headings of the `Types` and `Display ID helper` sections in `format-check.ts`, and of the `Helpers` sections in the `format-check`, `format-summary`, and `format-verbose` unit tests, with `// region | โ€ฆ` / `// endregion | โ€ฆ` folds, which the house style reserves for supporting blocks. (#947)
35
+ - Retitles the `Dependency updates` section of v11y-check's 0.14.1 changelog entry to `๐Ÿ“ฆ Dependencies`, in `.meta/changelog.json` and in the `CHANGELOG.md` rendered from it, so that the next release does not re-emit the retired title. (#950)
36
+
5
37
  ## 0.18.0 โ€” 2026-09-18
6
38
 
7
39
  ### ๐ŸŽ‰ Features
@@ -175,7 +207,7 @@ All notable changes to this project will be documented in this file.
175
207
 
176
208
  ## 0.14.1 โ€” 2026-08-04
177
209
 
178
- ### Dependency updates
210
+ ### ๐Ÿ“ฆ Dependencies
179
211
 
180
212
  - Bumped `@williamthorsen/nmr-core` to 0.9.1
181
213
 
package/README.md CHANGED
@@ -5,21 +5,17 @@
5
5
  Wraps [audit-ci](https://github.com/IBM/audit-ci) with a richer config model, typed JSON source of truth, and a sync workflow that automates allowlist management.
6
6
 
7
7
  <!-- section:release-notes -->
8
- ## Release notes โ€” v0.18.0 (2026-09-18)
8
+ ## Release notes โ€” v0.19.0 (2026-10-01)
9
9
 
10
10
  ### ๐ŸŽ‰ Features
11
11
 
12
- - Adopt output styles, shared glyphs, and column-aware wrapping (#836)
12
+ - Adds `v11y update-templates`, which writes `.github/workflows/audit.yaml` when it is missing or differs from the installed template, prints a diff of the update, and never reads or writes the config file. (#952)
13
+ - Changes the readyup kits' fix messages for a workflow that differs from its template, or that references a deprecated tag, to recommend `update-templates` rather than `init --force`. (#952)
13
14
 
14
- - Makes `v11y-check` print `check` and `init` output without emoji, and with a word such as `PASS` or `STALE` in place of each row marker, to whichever of stdout and stderr is not a terminal, or to both when `CI` is set.
15
- - Adds the `V11Y_CHECK_OUTPUT_STYLE` environment variable, which accepts `auto`, `plain`, or `rich`, overrides that detection, and makes any other value a usage error that exits with code 1.
16
- - Changes the emoji row markers of rich output: โŒ replaces ๐Ÿšจ for an unallowed row, โœ… replaces โš ๏ธ for an allowed row, โฉ replaces โ„น๏ธ for a below-threshold row, ๐Ÿงน replaces ๐Ÿ—‘๏ธ for a stale row, and the `allowed` and `ignored` suffixes of a compact row lose their emoji.
15
+ ### ๐Ÿ› Bug fixes
17
16
 
18
- - Give nmr plain output in pipes and CI logs (#838)
19
-
20
- - Stops `nmr` from printing emoji to a pipe or a CI log: When the output stream is not a terminal or `CI` is set, a verdict reads `PASS`, `FAIL`, `SKIP`, or `NOOP` and a command icon is omitted, so that a log can be searched for a verdict.
21
- - Adds `--output-style <auto|plain|rich>` to `nmr` and the `NMR_OUTPUT_STYLE` variable, each forcing either style; the flag outranks the variable, a value that names no style exits 1 with a usage error, and neither enters a check-cache key: A rich run and a plain run share a recorded pass.
22
- - Replaces several rich glyphs, taking the status markers from the set that release-kit and v11y-check print so that one status has one glyph across the three tools: a recalled pass shows โฉ in place of โญ๏ธ, a skipped empty override shows โšช in place of โ›”, a warning and the `--log` refusal show ๐ŸŸ  in place of โš ๏ธ and ๐Ÿ“ญ, the `--log` header shows ๐Ÿ’พ in place of ๐Ÿ“ผ, and `nmr-ensure-prepublish-hooks` reports โœ… and โŒ in place of โœ“ and โœ—.
17
+ - Rewords the `v11y-check` README and the message that `v11y` prints for missing build output, which addressed the reader in the second person and used em-dashes and figurative verbs. (#939)
18
+ - Fixes the issue that two comments in the `audit.yaml` workflow generated by `v11y init` did not follow the project's writing rules; the v11y-check kit check reports a previously generated `audit.yaml` as stale until `v11y init --force` regenerates it. (#946)
23
19
  <!-- /section:release-notes -->
24
20
 
25
21
  ## Installation
@@ -30,7 +26,7 @@ Requires Node.js 24 or later.
30
26
  pnpm add -D v11y-check
31
27
  ```
32
28
 
33
- The package is `v11y-check`; the bin is `v11y`. The package also ships `v11y-check` as a bin alias, so `pnpm exec v11y-check` and `npx v11y-check` continue to work.
29
+ The package is `v11y-check`; the bin is `v11y`. The package also declares `v11y-check` as a bin alias, so `pnpm exec v11y-check` and `npx v11y-check` continue to work.
34
30
 
35
31
  ## Quick start
36
32
 
@@ -48,7 +44,7 @@ npx v11y-check sync
48
44
  npx v11y-check --raw
49
45
  ```
50
46
 
51
- No config file is required. When `.config/v11y-check.config.json` is absent, the tool uses built-in defaults: `severityThreshold: 'moderate'` for dev, `severityThreshold: 'low'` for prod, and empty allowlists.
47
+ The tool does not require a config file. When `.config/v11y-check.config.json` is absent, the tool uses built-in defaults: `severityThreshold: 'moderate'` for dev, `severityThreshold: 'low'` for prod, and empty allowlists.
52
48
 
53
49
  ## Configuration
54
50
 
@@ -78,16 +74,16 @@ The source-of-truth config lives at `.config/v11y-check.config.json`:
78
74
 
79
75
  ### Fields
80
76
 
81
- - **`$schema`** (optional) โ€” JSON Schema URL for editor autocomplete and validation. Automatically included by `init` and `sync`.
82
- - **`dev`** / **`prod`** โ€” Scope-specific settings:
83
- - **`severityThreshold`** (optional) โ€” Fail on advisories at or above this severity. Valid values: `'low'`, `'moderate'`, `'high'`, `'critical'`. When omitted, audit-ci uses its own defaults.
84
- - **`allowlist`** โ€” Typed advisory entries with `id`, `path`, `url`, and optional `reason` and `addedAt`. `addedAt` is an ISO 8601 UTC datetime (e.g., `2026-04-15T09:30:00.000Z`) populated automatically by `v11y sync` on new entries; existing entries retain whatever value they had. Older `YYYY-MM-DD` values are still accepted.
77
+ - **`$schema`** (optional): JSON Schema URL for editor autocomplete and validation. Automatically included by `init` and `sync`.
78
+ - **`dev`** / **`prod`**: Scope-specific settings:
79
+ - **`severityThreshold`** (optional): Fail on advisories at or above this severity. Valid values: `'low'`, `'moderate'`, `'high'`, `'critical'`. When omitted, audit-ci uses its own defaults.
80
+ - **`allowlist`**: Typed advisory entries with `id`, `path`, `url`, and optional `reason` and `addedAt`. `addedAt` is an ISO 8601 UTC datetime (e.g., `2026-04-15T09:30:00.000Z`) populated automatically by `v11y sync` on new entries; existing entries retain whatever value they had. Older `YYYY-MM-DD` values are still accepted.
85
81
 
86
82
  ### Output style
87
83
 
88
84
  The `V11Y_CHECK_OUTPUT_STYLE` environment variable sets the style for every command, `init` included: `rich` marks each finding with an emoji, such as โŒ or โœ…, and `plain` prints a word in its place, such as `FAIL` or `PASS`, which a reader of a log can search for. `auto`, the default, defers to detection. Any other value is a usage error that exits with code 1.
89
85
 
90
- Detection decides stdout and stderr separately. A stream is plain when `CI` is set to anything other than an empty string or `false`, when the stream is not a terminal, or when `TERM` is `linux`; otherwise it is rich. `--json` output contains no emoji in either style.
86
+ Detection decides stdout and stderr separately. A stream is plain when `CI` is set to anything other than an empty string or `false`, when the stream is not a terminal, or when `TERM` is `linux`; otherwise it is rich. `--json` output does not contain any emoji in either style.
91
87
 
92
88
  ## CLI reference
93
89
 
@@ -99,6 +95,7 @@ Commands:
99
95
  check (default) Grouped vulnerability check with severity indicators
100
96
  sync Synchronize allowlists with current audit findings
101
97
  init Scaffold a starter config file and GitHub Actions workflow
98
+ update-templates Update the scaffolded workflow to the current template
102
99
 
103
100
  Scope options:
104
101
  --dev Target dev dependencies only
@@ -125,6 +122,12 @@ Environment:
125
122
  --force, -f Overwrite an existing workflow (an existing config is never overwritten)
126
123
  ```
127
124
 
125
+ ### Update-templates options
126
+
127
+ ```
128
+ --dry-run, -n Preview changes without writing files
129
+ ```
130
+
128
131
  ### JSON output shape
129
132
 
130
133
  `--json` emits one object per requested scope plus a top-level `summary` block:
@@ -150,15 +153,15 @@ Environment:
150
153
 
151
154
  ## Scaffolded GitHub Actions workflow
152
155
 
153
- `v11y init` scaffolds `.github/workflows/audit.yaml` alongside the config file. The workflow is a thin caller that delegates to the versioned reusable workflow published at `williamthorsen/node-monorepo-tools/.github/workflows/audit.reusable.yaml@workflow/audit-v1`, so your repository tracks the reusable workflow at a stable version tag.
156
+ `v11y init` scaffolds `.github/workflows/audit.yaml` alongside the config file. The workflow is a thin caller that delegates to the versioned reusable workflow published at `williamthorsen/node-monorepo-tools/.github/workflows/audit.reusable.yaml@workflow/audit-v1`, so the consuming repository tracks the reusable workflow at a stable version tag.
154
157
 
155
- The scaffolded workflow triggers on pull requests to `main`/`next`, on a daily schedule, and on manual `workflow_dispatch`. Commit the file into your repository so the caller runs in CI. If the reusable workflow's caller-side requirements change (for example, the tag bumps), re-run `v11y init --force` to refresh the file.
158
+ The scaffolded workflow triggers on pull requests to `main`/`next`, on a daily schedule, and on manual `workflow_dispatch`. Commit the file into the repository so that the caller runs in CI. If the reusable workflow's caller-side requirements change (for example, the tag bumps), run `v11y update-templates` to refresh the file, which shows what changed and leaves the config file untouched.
156
159
 
157
- The reusable workflow installs pnpm with [`pnpm/setup`](https://github.com/pnpm/setup), which installs pnpm 11 or newer only and reads the version from your `devEngines.packageManager` or `packageManager` field. A repository pinned below that cannot run it.
160
+ The reusable workflow installs pnpm with [`pnpm/setup`](https://github.com/pnpm/setup), which installs pnpm 11 or newer only and reads the version from the repository's `devEngines.packageManager` or `packageManager` field. A repository pinned below that cannot run it.
158
161
 
159
162
  ## Readiness checks
160
163
 
161
- v11y-check publishes a [readyup](https://www.npmjs.com/package/readyup) kit that checks a consuming repo against the release it has installed: that v11y-check is a devDependency at or above the current version, that audit-ci configs sit under `.config/audit-ci/`, and that `.github/workflows/audit.yaml` matches the template this package scaffolds. The kit ships inside the package, so it checks against the version you installed rather than whatever a repository ref happens to point at.
164
+ v11y-check publishes a [readyup](https://www.npmjs.com/package/readyup) kit that checks a consuming repo against the release that it has installed: that v11y-check is a devDependency at or above the current version, that audit-ci configs are under `.config/audit-ci/`, and that `.github/workflows/audit.yaml` matches the template scaffolded by this package. The kit is included in the package, so it checks against the installed version rather than whatever a repository ref happens to point at.
162
165
 
163
166
  Add `readyup` as a devDependency, then name v11y-check in its config:
164
167
 
@@ -172,12 +175,12 @@ export default defineRdyConfig({
172
175
  ```
173
176
 
174
177
  ```bash
175
- rdy run --packages # every kit each listed package publishes
178
+ rdy run --packages # every kit that each listed package publishes
176
179
  rdy run --from npm:v11y-check # v11y-check's kit alone, without the config entry
177
180
  rdy list --from npm:v11y-check # what v11y-check publishes
178
181
  ```
179
182
 
180
- `--packages` is the form that survives v11y-check publishing further kits. Every form needs `readyup` 0.23 or later, and `v11y-check` as a _direct_ devDependency: a strict pnpm layout links nothing else into the project, so a transitive copy is unreachable.
183
+ `--packages` is the form that keeps working if v11y-check publishes further kits. Every form needs `readyup` 0.23 or later, and `v11y-check` as a _direct_ devDependency: A strict pnpm layout links only direct dependencies into the project, which leaves a transitive copy unreachable.
181
184
 
182
185
  The kit is no longer reachable through `rdy run --from github:williamthorsen/node-monorepo-tools`. Repos still using that form should switch to one of the invocations above.
183
186
 
@@ -185,7 +188,7 @@ The kit is no longer reachable through `rdy run --from github:williamthorsen/nod
185
188
 
186
189
  v0.4 introduces breaking changes to the config schema:
187
190
 
188
- - **`outDir` removed.** Intermediate audit-ci files are now written to a temp directory and cleaned up automatically. Remove `outDir` from your config.
191
+ - **`outDir` removed.** Intermediate audit-ci files are now written to a temp directory and cleaned up automatically. Remove `outDir` from the config.
189
192
  - **Severity booleans replaced by `severityThreshold`.** Replace `"moderate": true` with `"severityThreshold": "moderate"`, `"high": true` with `"severityThreshold": "high"`, etc. Only one threshold per scope is supported.
190
193
  - **`generate` subcommand removed.** The `v11y generate` command no longer exists. Flat audit-ci configs are now managed internally.
191
194
  - **Config is optional.** All commands now work without a config file, using built-in defaults.
@@ -195,4 +198,4 @@ To migrate an existing config:
195
198
  1. Remove the `outDir` field.
196
199
  2. Replace severity booleans with `severityThreshold` in each scope.
197
200
  3. Optionally add a `$schema` field set to `https://github.com/williamthorsen/node-monorepo-tools/raw/v11y-check-v<version>/packages/v11y-check/schemas/config.json`, with `<version>` replaced by the installed v11y-check version.
198
- 4. Delete any generated `audit-ci.*.json` files that were in your config directory.
201
+ 4. Delete any generated `audit-ci.*.json` files that were in the config directory.
package/bin/v11y.js CHANGED
@@ -3,7 +3,7 @@ try {
3
3
  await import('../dist/esm/bin/v11y.js');
4
4
  } catch (error) {
5
5
  if (error.code === 'ERR_MODULE_NOT_FOUND') {
6
- process.stderr.write('v11y: build output not found โ€” run `nmr build` first\n');
6
+ process.stderr.write('v11y: build output not found; run `nmr build` first\n');
7
7
  } else {
8
8
  process.stderr.write(`v11y: failed to load: ${error.message}\n`);
9
9
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Route CLI arguments to the appropriate subcommand.
2
+ * Routes CLI arguments to the appropriate subcommand.
3
3
  *
4
4
  * Returns a numeric exit code: 0 for success, 1 for errors.
5
5
  */
@@ -3,9 +3,10 @@ import { parseArgs, readPackageVersion, reportError } from '@williamthorsen/nmr-
3
3
  import { describeError } from '@williamthorsen/toolbelt.errors';
4
4
  import { auditCommand, checkCommand, syncCommand } from "../cli.js";
5
5
  import { initCommand } from "../init/initCommand.js";
6
+ import { updateTemplatesCommand } from "../init/updateTemplatesCommand.js";
6
7
  import { OUTPUT_STYLE_ENV_VAR, resolveStyles } from "../resolveStyles.js";
7
8
  const VERSION = readPackageVersion(import.meta.url);
8
- const SUBCOMMANDS = ['check', 'init', 'sync'];
9
+ const SUBCOMMANDS = ['check', 'init', 'sync', 'update-templates'];
9
10
  const MIN_PREFIX_LENGTH = 3;
10
11
  function showHelp() {
11
12
  console.info(`
@@ -16,6 +17,7 @@ Commands:
16
17
  check (default) Grouped vulnerability check with severity indicators
17
18
  sync Synchronize allowlists with current audit findings
18
19
  init Scaffold a starter config file and GitHub Actions workflow
20
+ update-templates Update the scaffolded workflow to the current template
19
21
 
20
22
  Scope options:
21
23
  --dev Target dev dependencies only
@@ -63,6 +65,19 @@ Other options:
63
65
  --help, -h Show this help message
64
66
  `);
65
67
  }
68
+ function showUpdateTemplatesHelp() {
69
+ console.info(`
70
+ Usage: v11y update-templates [options]
71
+
72
+ Update .github/workflows/audit.yaml to the template of the installed version,
73
+ showing what changed. Creates the workflow when it is missing. Never touches
74
+ the config file.
75
+
76
+ Options:
77
+ --dry-run, -n Preview changes without writing files
78
+ --help, -h Show this help message
79
+ `);
80
+ }
66
81
  function parseSharedFlags(flags, styles) {
67
82
  const flagSchema = {
68
83
  config: { long: '--config', type: 'string' },
@@ -126,6 +141,9 @@ export async function routeCommand(args) {
126
141
  if (command === 'sync') {
127
142
  return handleSubcommand(args.slice(1), styles, syncCommand, showSyncHelp);
128
143
  }
144
+ if (command === 'update-templates') {
145
+ return handleUpdateTemplates(args.slice(1), styles);
146
+ }
129
147
  if (command !== undefined && !command.startsWith('-')) {
130
148
  const typoMatch = findTypoMatch(command);
131
149
  if (typoMatch !== undefined) {
@@ -181,3 +199,21 @@ function handleInit(flags, styles) {
181
199
  }
182
200
  return initCommand({ dryRun: parsed.flags.dryRun, force: parsed.flags.force, styles });
183
201
  }
202
+ function handleUpdateTemplates(flags, styles) {
203
+ if (flags.some((f) => f === '--help' || f === '-h')) {
204
+ showUpdateTemplatesHelp();
205
+ return 0;
206
+ }
207
+ const updateTemplatesFlagSchema = {
208
+ dryRun: { long: '--dry-run', type: 'boolean', short: '-n' },
209
+ };
210
+ let parsed;
211
+ try {
212
+ parsed = parseArgs(flags, updateTemplatesFlagSchema);
213
+ }
214
+ catch (error) {
215
+ reportError(describeError(error));
216
+ return 1;
217
+ }
218
+ return updateTemplatesCommand({ dryRun: parsed.flags.dryRun, styles });
219
+ }
package/dist/esm/cli.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { type CommandOptions } from './types.js';
2
2
  /**
3
- * Run the default audit command (CI mode).
3
+ * Runs the default audit command (CI mode).
4
4
  *
5
5
  * Generates config, invokes audit-ci for each scope, and returns a combined exit code.
6
6
  */
7
7
  export declare function auditCommand(options: CommandOptions): Promise<number>;
8
8
  /**
9
- * Run the default grouped-check command.
9
+ * Runs the default grouped-check command.
10
10
  *
11
11
  * Audits each scope without allowlist filtering, cross-references results with
12
12
  * the config allowlist, detects stale entries, and produces grouped output.
@@ -14,10 +14,10 @@ export declare function auditCommand(options: CommandOptions): Promise<number>;
14
14
  */
15
15
  export declare function checkCommand(options: CommandOptions): Promise<number>;
16
16
  /**
17
- * Run the `sync` subcommand.
17
+ * Runs the `sync` subcommand.
18
18
  *
19
19
  * Audits each scope in report mode without allowlist filtering, then updates
20
- * the allowlist to match current findings. When no config file exists, creates
21
- * one at the default path.
20
+ * the allowlist to match current findings. When the config file doesn't exist,
21
+ * creates one at the default path.
22
22
  */
23
23
  export declare function syncCommand(options: CommandOptions): Promise<number>;
@@ -1,7 +1,7 @@
1
1
  import { type V11yCheckConfig } from './types.js';
2
2
  /** Default config file path, relative to the working directory. */
3
3
  export declare const DEFAULT_CONFIG_PATH = ".config/v11y-check.config.json";
4
- /** Discriminate between a config loaded from a file and one built from defaults. */
4
+ /** Discriminates between a config loaded from a file and one built from defaults. */
5
5
  export type ConfigSource = 'defaults' | 'file';
6
6
  /** Result of loading config, including the source discriminator. */
7
7
  export interface LoadConfigResult {
@@ -11,7 +11,7 @@ export interface LoadConfigResult {
11
11
  configSource: ConfigSource;
12
12
  }
13
13
  /**
14
- * Load and validate the v11y-check config from disk, falling back to defaults.
14
+ * Loads and validates the v11y-check config from disk, falling back to defaults.
15
15
  *
16
16
  * When `configPath` is explicitly provided, the file must exist. When omitted,
17
17
  * the default path is tried; if absent, `DEFAULT_CONFIG` is returned.
@@ -1,7 +1,7 @@
1
1
  import type { CheckResult } from './format-check.js';
2
2
  import type { AuditScope } from './types.js';
3
3
  /**
4
- * Compute the "Actions:" footer for check output.
4
+ * Computes the "Actions:" footer for check output.
5
5
  *
6
6
  * Returns an empty string when the allowlist is fully current. Otherwise returns
7
7
  * a bulleted action list with a verbose hint (when vulns exist) and a sync hint.
@@ -1,6 +1,6 @@
1
1
  import { type OutputStyle } from '@williamthorsen/nmr-core';
2
2
  import type { AuditResult, AuditScope, SeverityThreshold } from './types.js';
3
- /** Classification of an allowlist entry relative to current audit findings. */
3
+ /** An audit finding that the allowlist admits, with the entry's reason and date. */
4
4
  export interface AllowedVuln {
5
5
  addedAt?: string | undefined;
6
6
  cvss?: {
@@ -35,19 +35,19 @@ export interface CheckResult {
35
35
  }
36
36
  /** Maps a severity string to its indicator in a style: a colored circle when rich, nothing when plain. */
37
37
  export declare function severityIndicator(severity: string | undefined, style: OutputStyle): string;
38
- /** Resolve the best display ID for a vulnerability: GHSA ID if available, otherwise the numeric ID. */
38
+ /** Resolves the best display ID for a vulnerability: GHSA ID if available, otherwise the numeric ID. */
39
39
  export declare function displayId(vuln: {
40
40
  ghsaId?: string | undefined;
41
41
  id: string;
42
42
  }): string;
43
- /** Build the severity suffix for a finding line, e.g. ` ๐Ÿ”ด critical`. */
43
+ /** Builds the severity suffix for a finding line, e.g. ` ๐Ÿ”ด critical`. */
44
44
  export declare function formatSeveritySuffix(severity: string | undefined, style: OutputStyle): string;
45
45
  /**
46
- * Format check results as human-readable text output.
46
+ * Formats check results as human-readable text output.
47
47
  *
48
48
  * Produces an intro banner, scoped findings with severity labels and GHSA IDs,
49
49
  * and an action hints footer.
50
50
  */
51
51
  export declare function formatCheckText(result: CheckResult, scopes: AuditScope[], style: OutputStyle, now?: Date, thresholds?: Partial<Record<AuditScope, SeverityThreshold>>): string;
52
- /** Format check results as a JSON string with a top-level `summary` block derived from the result. */
52
+ /** Formats check results as a JSON string with a top-level `summary` block derived from the result. */
53
53
  export declare function formatCheckJson(result: CheckResult, scopes: AuditScope[]): string;
@@ -8,10 +8,10 @@ export interface CheckSummary {
8
8
  count: number;
9
9
  }
10
10
  /**
11
- * Derive the headline summary from a check result.
11
+ * Derives the headline summary from a check result.
12
12
  *
13
13
  * Priority is severity-driven: unallowed > allowed > stale > none. The count is the total across
14
14
  * the requested scopes for the *active* category only; for `'none'` it is `0`. Below-threshold
15
- * findings never affect the summary โ€” the threshold already excludes them from pass/fail.
15
+ * findings never affect the summary: The threshold already excludes them from pass/fail.
16
16
  */
17
17
  export declare function deriveSummary(result: CheckResult, scopes: AuditScope[]): CheckSummary;
@@ -1,10 +1,8 @@
1
1
  /**
2
- * Produce a human-readable relative-time string such as "just now", "N minutes ago",
2
+ * Produces a human-readable relative-time string such as "just now", "N minutes ago",
3
3
  * "yesterday", "N months ago", "N years ago".
4
4
  *
5
5
  * Uses millisecond math for units up through weeks to avoid DST/timezone drift on
6
6
  * short intervals, and UTC calendar math for months and years.
7
- *
8
- * @internal โ€” exported for test access; consumers should use higher-level formatting helpers.
9
7
  */
10
8
  export declare function formatRelativeTime(fromIso: string, now: Date): string;
@@ -1,5 +1,5 @@
1
1
  import { type OutputStyle } from '@williamthorsen/nmr-core';
2
2
  import { type CheckResult } from './format-check.js';
3
3
  import type { AuditScope, SeverityThreshold } from './types.js';
4
- /** Format the verbose per-vulnerability check output as text. */
4
+ /** Formats the verbose per-vulnerability check output as text. */
5
5
  export declare function formatCheckVerboseText(result: CheckResult, scopes: AuditScope[], style: OutputStyle, now?: Date, thresholds?: Partial<Record<AuditScope, SeverityThreshold>>): string;
@@ -6,7 +6,7 @@ interface AuditCiFlatConfig {
6
6
  'show-not-found'?: boolean;
7
7
  }
8
8
  /**
9
- * Transform a scope config into the flat JSON structure audit-ci expects.
9
+ * Transforms a scope config into the flat JSON structure that audit-ci expects.
10
10
  *
11
11
  * Translates `severityThreshold` to the corresponding audit-ci boolean,
12
12
  * adds scope-specific flags (`skip-dev` for prod, `extra-args: ["--dev"]` for dev),
@@ -14,10 +14,10 @@ interface AuditCiFlatConfig {
14
14
  */
15
15
  export declare function buildFlatConfig(scopeConfig: ScopeConfig, scope: AuditScope): AuditCiFlatConfig;
16
16
  /**
17
- * Generate the audit-ci config file for a scope and write it to disk.
17
+ * Generates the audit-ci config file for a scope and writes it to disk.
18
18
  *
19
19
  * The output path is `{outputDir}/audit-ci.{scope}.json`. The caller must
20
- * ensure `outputDir` already exists (e.g., via `withTempDir`).
20
+ * ensure that `outputDir` exists.
21
21
  */
22
22
  export declare function generateAuditCiConfig(scopeConfig: ScopeConfig, scope: AuditScope, outputDir: string): Promise<string>;
23
23
  export {};
@@ -1,7 +1,7 @@
1
1
  import { type OutputStyle, type StatusGlyphName } from '@williamthorsen/nmr-core';
2
2
  /**
3
- * Glyphs that name no status; a status marker comes from nmr-core's `STATUS_GLYPHS`. A plain variant is empty
4
- * where a word always follows the glyph.
3
+ * Glyphs that don't name a status; a status marker comes from nmr-core's `STATUS_GLYPHS`. A plain variant is empty
4
+ * for a glyph that a word always follows.
5
5
  */
6
6
  export declare const V11Y_GLYPHS: Readonly<Record<"plain" | "rich", Readonly<Record<"audit" | "scopeDev" | "scopeProd" | "severityHigh" | "severityLow" | "severityModerate" | "stale", import("@williamthorsen/toolbelt.terminal/candidate").Glyph>>>>;
7
7
  export type V11yGlyphName = keyof (typeof V11Y_GLYPHS)['rich'];
@@ -9,5 +9,5 @@ export type V11yGlyphName = keyof (typeof V11Y_GLYPHS)['rich'];
9
9
  export type RowMarkerName = StatusGlyphName | 'stale';
10
10
  /** Renders a row marker and a message, padding the marker so that messages align across markers. */
11
11
  export declare function formatMarkedLine(style: OutputStyle, name: RowMarkerName, message: string): string;
12
- /** Reports the cells taken by the widest row marker in a style. */
12
+ /** Returns the number of cells taken by the widest row marker in a style. */
13
13
  export declare function measureRowMarkerColumn(style: OutputStyle): number;
@@ -5,7 +5,7 @@ interface InitOptions {
5
5
  styles: StreamStyles;
6
6
  }
7
7
  /**
8
- * Run the `v11y init` command.
8
+ * Runs the `v11y init` command.
9
9
  *
10
10
  * Scaffolds the starter config file and the GitHub Actions workflow, then prints next steps.
11
11
  * Returns the process exit code (0 for success, 1 if any write failed).
@@ -1,4 +1,5 @@
1
1
  import { type WriteResult } from '@williamthorsen/nmr-core';
2
+ export declare const WORKFLOW_PATH = ".github/workflows/audit.yaml";
2
3
  interface ScaffoldOptions {
3
4
  dryRun: boolean;
4
5
  force: boolean;
@@ -7,30 +8,25 @@ interface ScaffoldResult {
7
8
  configResult: WriteResult;
8
9
  }
9
10
  /**
10
- * Scaffold the v11y-check config file with sensible defaults, never overwriting an existing one, whose allowlist
11
+ * Scaffolds the v11y-check config file with sensible defaults, never overwriting an existing one, whose allowlist
11
12
  * `v11y sync` maintains.
12
- *
13
- * Returns `{ configResult }` to preserve the signature consumed by `syncCommand`, which predates
14
- * the workflow scaffolding and treats the config result as a named field.
15
13
  */
16
14
  export declare function scaffoldConfig({ dryRun }: {
17
15
  dryRun: boolean;
18
16
  }): ScaffoldResult;
19
- /** Copy the bundled audit.yaml.template to `.github/workflows/audit.yaml` in the target repo. */
17
+ /** Copies the bundled audit.yaml.template to `.github/workflows/audit.yaml` in the target repo. */
20
18
  export declare function copyWorkflowTemplate(dryRun: boolean, overwrite: boolean): WriteResult;
21
- /**
22
- * Scaffold the GitHub Actions audit workflow to `.github/workflows/audit.yaml`.
23
- *
24
- * Wraps `copyWorkflowTemplate` to provide a stable seam for future post-write transformations
25
- * (e.g., variable substitution) without changing call sites.
26
- */
19
+ /** Reads the bundled audit.yaml.template, returning a description of the failure when it cannot. */
20
+ export declare function readWorkflowTemplate(): {
21
+ content: string;
22
+ } | {
23
+ error: string;
24
+ };
25
+ /** Scaffolds the GitHub Actions audit workflow to `.github/workflows/audit.yaml`. */
27
26
  export declare function scaffoldWorkflow(dryRun: boolean, overwrite: boolean): WriteResult;
28
27
  /**
29
- * Scaffold v11y-check files for the target repo.
30
- *
31
- * Writes both the config file and the GitHub Actions workflow. Returns a flat array of write
32
- * results in the order [config, workflow]. `ScaffoldOptions.force` is translated to `overwrite`
33
- * for the workflow alone; an existing config is never overwritten.
28
+ * Scaffolds the config file and the GitHub Actions workflow, returning their write results in that order. `force`
29
+ * overwrites the workflow alone; an existing config is never overwritten.
34
30
  */
35
31
  export declare function scaffoldFiles({ dryRun, force }: ScaffoldOptions): WriteResult[];
36
32
  export {};
@@ -4,34 +4,33 @@ import { findPackageRoot, writeFileWithCheck } from '@williamthorsen/nmr-core';
4
4
  import { describeError } from '@williamthorsen/toolbelt.errors';
5
5
  import { v11yCheckConfigTemplate } from "./templates.js";
6
6
  const CONFIG_PATH = '.config/v11y-check.config.json';
7
- const WORKFLOW_PATH = '.github/workflows/audit.yaml';
7
+ export const WORKFLOW_PATH = '.github/workflows/audit.yaml';
8
8
  export function scaffoldConfig({ dryRun }) {
9
9
  const configResult = writeFileWithCheck(CONFIG_PATH, v11yCheckConfigTemplate, { dryRun, overwrite: false });
10
10
  return { configResult };
11
11
  }
12
12
  export function copyWorkflowTemplate(dryRun, overwrite) {
13
+ const template = readWorkflowTemplate();
14
+ if ('error' in template) {
15
+ return { filePath: WORKFLOW_PATH, outcome: 'failed', error: template.error };
16
+ }
17
+ return writeFileWithCheck(WORKFLOW_PATH, template.content, { dryRun, overwrite });
18
+ }
19
+ export function readWorkflowTemplate() {
13
20
  let root;
14
21
  try {
15
22
  root = findPackageRoot(import.meta.url);
16
23
  }
17
24
  catch (error) {
18
- const message = describeError(error);
19
- return { filePath: WORKFLOW_PATH, outcome: 'failed', error: `Failed to resolve package root: ${message}` };
25
+ return { error: `Failed to resolve package root: ${describeError(error)}` };
20
26
  }
21
27
  const templatePath = resolve(root, 'templates', 'audit.yaml.template');
22
- let content;
23
28
  try {
24
- content = readFileSync(templatePath, 'utf8');
29
+ return { content: readFileSync(templatePath, 'utf8') };
25
30
  }
26
31
  catch (error) {
27
- const message = describeError(error);
28
- return {
29
- filePath: WORKFLOW_PATH,
30
- outcome: 'failed',
31
- error: `Failed to read bundled template at ${templatePath}: ${message}`,
32
- };
32
+ return { error: `Failed to read bundled template at ${templatePath}: ${describeError(error)}` };
33
33
  }
34
- return writeFileWithCheck(WORKFLOW_PATH, content, { dryRun, overwrite });
35
34
  }
36
35
  export function scaffoldWorkflow(dryRun, overwrite) {
37
36
  return copyWorkflowTemplate(dryRun, overwrite);
@@ -0,0 +1,12 @@
1
+ import { type StreamStyles } from '@williamthorsen/nmr-core';
2
+ interface UpdateTemplatesOptions {
3
+ dryRun: boolean;
4
+ styles: StreamStyles;
5
+ }
6
+ /**
7
+ * Runs the `v11y update-templates` command and returns the process exit code.
8
+ *
9
+ * Brings the scaffolded audit workflow up to date with the bundled template; the config file is never read or written.
10
+ */
11
+ export declare function updateTemplatesCommand({ dryRun, styles }: UpdateTemplatesOptions): number;
12
+ export {};
@@ -0,0 +1,14 @@
1
+ import { printStep, reportTemplateUpdate, updateManagedFile, } from '@williamthorsen/nmr-core';
2
+ import { readWorkflowTemplate, WORKFLOW_PATH } from "./scaffold.js";
3
+ export function updateTemplatesCommand({ dryRun, styles }) {
4
+ if (dryRun) {
5
+ console.info('[dry-run mode]');
6
+ }
7
+ printStep('Updating workflows');
8
+ const template = readWorkflowTemplate();
9
+ const result = 'error' in template
10
+ ? { filePath: WORKFLOW_PATH, outcome: 'failed', error: template.error }
11
+ : updateManagedFile(WORKFLOW_PATH, template.content, { dryRun });
12
+ reportTemplateUpdate(result, dryRun, styles);
13
+ return result.outcome === 'failed' ? 1 : 0;
14
+ }
@@ -1,10 +1,10 @@
1
1
  import { type StreamStyles } from '@williamthorsen/nmr-core';
2
- /** The environment variable holding the caller's standing style preference: `auto`, `plain`, or `rich`. */
2
+ /** The environment variable that sets the caller's standing style preference: `auto`, `plain`, or `rich`. */
3
3
  export declare const OUTPUT_STYLE_ENV_VAR = "V11Y_CHECK_OUTPUT_STYLE";
4
4
  export interface ResolveStylesOptions {
5
5
  readonly env: Readonly<Record<string, string | undefined>>;
6
6
  readonly stderrIsTty: boolean;
7
7
  readonly stdoutIsTty: boolean;
8
8
  }
9
- /** Resolves the style of each output stream, reporting a usage error and returning `undefined` when the variable names no setting. */
9
+ /** Resolves the style of each output stream, reporting a usage error and returning `undefined` when the variable doesn't name a setting. */
10
10
  export declare function resolveStyles(options: ResolveStylesOptions): StreamStyles | undefined;
@@ -1,5 +1,5 @@
1
1
  import type { AuditResult } from './types.js';
2
- /** Resolve the audit-ci binary path from node_modules. */
2
+ /** Resolves the audit-ci binary path from node_modules. */
3
3
  export declare function resolveAuditCiBin(): string;
4
4
  /** Result of parsing audit-ci output, including any warnings. */
5
5
  export interface ParseResult {
@@ -7,7 +7,7 @@ export interface ParseResult {
7
7
  warnings: string[];
8
8
  }
9
9
  /**
10
- * Parse audit-ci JSON output into typed audit results.
10
+ * Parses audit-ci JSON output into typed audit results.
11
11
  *
12
12
  * Extracts advisories from the JSON, mapping each to an `AuditResult` with
13
13
  * the first discovered dependency path. Returns warnings when input is
@@ -19,7 +19,7 @@ export interface StaleEntriesResult {
19
19
  entries: string[];
20
20
  warnings: string[];
21
21
  }
22
- /** Extract stale allowlist entries from audit-ci JSON output. */
22
+ /** Extracts stale allowlist entries from audit-ci JSON output. */
23
23
  export declare function extractStaleEntries(jsonString: string): StaleEntriesResult;
24
24
  /** Options for running audit-ci. */
25
25
  interface RunAuditOptions {
@@ -37,7 +37,7 @@ export interface AuditRunResult {
37
37
  warnings: string[];
38
38
  }
39
39
  /**
40
- * Invoke audit-ci with the given config file in normal (CI) mode.
40
+ * Invokes audit-ci with the given config file in normal (CI) mode.
41
41
  *
42
42
  * Returns the exit code faithfully. When `json` is true, output is JSON;
43
43
  * otherwise audit-ci uses its default text format. Stale overrides are
@@ -51,10 +51,6 @@ export interface ReportResult {
51
51
  stderr: string;
52
52
  warnings: string[];
53
53
  }
54
- /**
55
- * Invoke audit-ci in report mode (no allowlist filtering, swallows exit code).
56
- *
57
- * Always returns exit code 0. Parses JSON output into typed `AuditResult` objects.
58
- */
54
+ /** Invokes audit-ci with JSON output, ignoring its exit code, and parses the advisories into `AuditResult` objects. */
59
55
  export declare function runReport({ configPath, cwd, reportType }: Omit<RunAuditOptions, 'json'>): ReportResult;
60
56
  export {};
@@ -1,7 +1,7 @@
1
1
  import type { AllowlistEntry, AuditResult, AuditScope, V11yCheckConfig } from './types.js';
2
- /** Produce a full ISO 8601 UTC datetime string. */
2
+ /** Produces a full ISO 8601 UTC datetime string. */
3
3
  export declare function formatUtcDatetime(date: Date): string;
4
- /** Format a Date as a human-friendly UTC string for use in reason messages. */
4
+ /** Formats a Date as a human-friendly UTC string for use in reason messages. */
5
5
  export declare function formatFriendlyUtc(date: Date): string;
6
6
  /** Result of a sync operation for a single scope. */
7
7
  export interface SyncResult {
@@ -11,10 +11,10 @@ export interface SyncResult {
11
11
  scope: AuditScope;
12
12
  }
13
13
  /**
14
- * Compute the updated allowlist by diffing audit results against the current entries.
14
+ * Computes the updated allowlist by diffing audit results against the current entries.
15
15
  *
16
16
  * New advisories are added with an auto-populated reason. Resolved advisories are removed.
17
- * Existing entries with a non-empty reason are preserved.
17
+ * Existing entries are kept unchanged.
18
18
  */
19
19
  export declare function computeSyncDiff(currentAllowlist: AllowlistEntry[], auditResults: AuditResult[], date?: Date): {
20
20
  added: AllowlistEntry[];
@@ -22,19 +22,19 @@ export declare function computeSyncDiff(currentAllowlist: AllowlistEntry[], audi
22
22
  removed: AllowlistEntry[];
23
23
  };
24
24
  /**
25
- * Build the updated config by replacing the allowlist for the given scope.
25
+ * Builds the updated config by replacing the allowlist for the given scope with its entries sorted by ID.
26
26
  *
27
27
  * Returns a new config object; does not mutate the input.
28
28
  */
29
29
  export declare function buildUpdatedConfig(config: V11yCheckConfig, scope: AuditScope, newAllowlist: AllowlistEntry[]): V11yCheckConfig;
30
30
  /**
31
- * Serialize the config to JSON with alphabetically ordered allowlist entry keys.
31
+ * Serializes the config to JSON with alphabetically ordered allowlist entry keys.
32
32
  *
33
- * Includes `$schema` when present. Uses `severityThreshold` instead of boolean fields.
33
+ * Includes `$schema` when present.
34
34
  */
35
35
  export declare function serializeConfig(config: V11yCheckConfig): string;
36
36
  /**
37
- * Synchronize the allowlist for a scope by diffing audit results against the current config.
37
+ * Synchronizes the allowlist for a scope by diffing audit results against the current config.
38
38
  *
39
39
  * Returns the sync diff and the updated config. Writes the updated config to disk.
40
40
  */
package/dist/esm/sync.js CHANGED
@@ -53,7 +53,7 @@ export function computeSyncDiff(currentAllowlist, auditResults, date) {
53
53
  return { added, kept, removed };
54
54
  }
55
55
  export function buildUpdatedConfig(config, scope, newAllowlist) {
56
- const sorted = [...newAllowlist].sort((a, b) => a.id.localeCompare(b.id));
56
+ const sorted = newAllowlist.toSorted((a, b) => a.id.localeCompare(b.id));
57
57
  return {
58
58
  ...config,
59
59
  [scope]: {
package/dist/esm/tmp.d.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  /**
2
- * Execute a callback with a temporary directory, ensuring cleanup afterward.
2
+ * Executes a callback with a temporary directory, ensuring cleanup afterward.
3
3
  *
4
4
  * Creates a unique temp directory under `os.tmpdir()` and removes it
5
5
  * (recursively) when the callback completes or throws.
6
- *
7
- * @internal Exported for testing.
8
6
  */
9
7
  export declare function withTempDir<T>(fn: (tempDir: string) => Promise<T>): Promise<T>;
@@ -27,7 +27,7 @@ export declare const allowlistEntrySchema: z.ZodObject<{
27
27
  /** Configuration for a single audit scope (dev or prod). */
28
28
  export interface ScopeConfig {
29
29
  allowlist: AllowlistEntry[];
30
- /** Fail on advisories at or above this severity. */
30
+ /** Severity at or above which an advisory fails the audit. */
31
31
  severityThreshold?: SeverityThreshold | undefined;
32
32
  }
33
33
  /** Zod schema for a scope configuration block. */
@@ -86,7 +86,7 @@ export declare const v11yCheckConfigSchema: z.ZodObject<{
86
86
  }>>;
87
87
  }, z.core.$strict>;
88
88
  }, z.core.$strict>;
89
- /** Built-in defaults used when no config file is present. */
89
+ /** Built-in defaults used when the config file isn't present. */
90
90
  export declare const DEFAULT_CONFIG: V11yCheckConfig;
91
91
  /** A single vulnerability found by audit-ci. */
92
92
  export interface AuditResult {
@@ -112,11 +112,9 @@ export interface CommandOptions {
112
112
  verbose: boolean;
113
113
  }
114
114
  /**
115
- * Determine whether a severity string is at or above the given threshold.
115
+ * Determines whether a severity string is at or above the given threshold.
116
116
  *
117
117
  * Unrecognized or undefined severities are treated as above threshold
118
- * (conservative โ€” surfaces unknown vulns rather than hiding them).
119
- *
120
- * @internal Exported for testing.
118
+ * (conservative: An unknown vuln is reported rather than hidden).
121
119
  */
122
120
  export declare function isSeverityAtOrAbove(severity: string | undefined, threshold: SeverityThreshold): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "v11y-check",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "private": false,
5
5
  "description": "Wrap audit-ci with a richer config model, typed JSON source of truth, and sync workflow",
6
6
  "keywords": [
@@ -45,15 +45,16 @@
45
45
  "templates"
46
46
  ],
47
47
  "dependencies": {
48
- "@williamthorsen/nmr-core": "0.12.0",
48
+ "@williamthorsen/nmr-core": "0.13.1",
49
49
  "@williamthorsen/toolbelt.errors": "0.8.1",
50
50
  "audit-ci": "7.1.0",
51
- "zod": "4.6.2"
51
+ "zod": "4.6.5"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@williamthorsen/toolbelt.filesystem": "0.9.1",
55
55
  "@williamthorsen/toolbelt.testing": "0.6.1",
56
56
  "@williamthorsen/toolbelt.vitest": "0.10.1",
57
+ "esbuild": "0.28.2",
57
58
  "readyup": "0.38.0",
58
59
  "vitest": "4.1.11"
59
60
  },
@@ -7,7 +7,7 @@ on:
7
7
  - main
8
8
  - next
9
9
 
10
- # Daily schedule โ€” adjust cron expression per repo if a different cadence is desired.
10
+ # Run daily. Adjust the cron expression in a repo that needs a different cadence.
11
11
  schedule:
12
12
  - cron: '0 8 * * *'
13
13
 
@@ -16,7 +16,7 @@ on:
16
16
  # Permissions must be declared here. The GITHUB_TOKEN scope passed to the called
17
17
  # reusable workflow is bounded by this caller's permissions block; when omitted,
18
18
  # the repository's default workflow permissions apply (read-only here), which would
19
- # silently deny the issues/pull-requests writes the reusable workflow needs.
19
+ # silently deny the issue and pull-request writes that the reusable workflow needs.
20
20
  permissions:
21
21
  contents: read
22
22
  issues: write