@vertaaux/cli 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +28 -1
- package/dist/app/interactive-app.d.ts +2 -0
- package/dist/app/interactive-app.d.ts.map +1 -1
- package/dist/app/interactive-app.js +26 -7
- package/dist/app/menu/categories.d.ts +2 -2
- package/dist/app/menu/categories.d.ts.map +1 -1
- package/dist/app/menu/categories.js +3 -18
- package/dist/app/views/command-runner.d.ts.map +1 -1
- package/dist/app/views/command-runner.js +52 -9
- package/dist/app/views/help-overlay.d.ts +1 -1
- package/dist/app/views/help-overlay.d.ts.map +1 -1
- package/dist/app/views/help-overlay.js +5 -4
- package/dist/commands/a11y.d.ts +4 -2
- package/dist/commands/a11y.d.ts.map +1 -1
- package/dist/commands/a11y.js +82 -9
- package/dist/commands/audit/index.d.ts.map +1 -1
- package/dist/commands/audit/index.js +33 -8
- package/dist/commands/audit/output.d.ts.map +1 -1
- package/dist/commands/audit/output.js +3 -4
- package/dist/commands/audit/policy.d.ts +10 -2
- package/dist/commands/audit/policy.d.ts.map +1 -1
- package/dist/commands/audit/policy.js +47 -2
- package/dist/commands/audit/types.d.ts +1 -0
- package/dist/commands/audit/types.d.ts.map +1 -1
- package/dist/commands/baseline.d.ts +1 -0
- package/dist/commands/baseline.d.ts.map +1 -1
- package/dist/commands/baseline.js +26 -12
- package/dist/commands/comment.d.ts.map +1 -1
- package/dist/commands/comment.js +8 -7
- package/dist/commands/compare.js +3 -3
- package/dist/commands/diff.d.ts +2 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +23 -12
- package/dist/commands/doc.js +2 -2
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/explain.js +3 -3
- package/dist/commands/fix-all.js +2 -2
- package/dist/commands/fix-plan.d.ts.map +1 -1
- package/dist/commands/fix-plan.js +4 -3
- package/dist/commands/fix.js +5 -5
- package/dist/commands/patch-review.js +2 -2
- package/dist/commands/policy.js +2 -2
- package/dist/commands/release-notes.js +3 -3
- package/dist/commands/suggest.d.ts.map +1 -1
- package/dist/commands/suggest.js +28 -2
- package/dist/commands/triage.js +3 -3
- package/dist/commands/verify.js +3 -3
- package/dist/config/schema.d.ts +4 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/output/envelope.d.ts +8 -1
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js +24 -6
- package/dist/policy/schema.d.ts +137 -0
- package/dist/policy/schema.d.ts.map +1 -1
- package/dist/policy/schema.js +107 -0
- package/dist/prompts/command-catalog.js +9 -9
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +30 -28
- package/dist/utils/root-args.d.ts +12 -0
- package/dist/utils/root-args.d.ts.map +1 -0
- package/dist/utils/root-args.js +44 -0
- package/dist/utils/stdin.d.ts +7 -0
- package/dist/utils/stdin.d.ts.map +1 -1
- package/dist/utils/stdin.js +32 -2
- package/node_modules/@vertaaux/tui/dist/index.cjs +505 -9
- package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
- package/node_modules/@vertaaux/tui/dist/index.js +502 -8
- package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
- package/node_modules/@vertaaux/tui/package.json +2 -3
- package/node_modules/chalk/license +9 -0
- package/node_modules/chalk/package.json +83 -0
- package/node_modules/chalk/readme.md +297 -0
- package/node_modules/chalk/source/index.d.ts +325 -0
- package/node_modules/chalk/source/index.js +225 -0
- package/node_modules/chalk/source/utilities.js +33 -0
- package/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
- package/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
- package/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
- package/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
- package/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
- package/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
- package/package.json +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ All notable changes to `@vertaaux/cli` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.5.1] - 2026-04-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`--profile <name>` flag on `vertaa audit`** — Phase 1.5 of audit profiles is now live on npm. `vertaa audit <url> --profile wcag-aa` (and any profile with a `categories` subset) skips auditors in the cloud worker rather than running all 7 and filtering post-run. Built-in profiles: `wcag-aa`, `conversion-focus`, `quick-ux`, `ci-gate`, `compliance`. The CLI passes `profile.categories` in the POST body via `apiRequest` when a category subset is resolved; the SDK path is used when no subset applies. See `cli/tests/commands/audit-handler.test.ts` for coverage.
|
|
15
|
+
- **`a11y` command upgrade** — `vertaa a11y <url>` now calls the dedicated `/v1/a11y/audit` endpoint with multi-engine analysis (axe-core + AccessLint + custom analyzers). Added `--mode`, `--fail-on-score`, `--min-impact`, and `--fail-on-findings` flags.
|
|
16
|
+
- **Source tracking** — All CLI-triggered audits now include `source: "cli"` metadata for dashboard visibility.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **Profile-filtered categories now report `null` instead of a false `100`** — Excluded categories in `scores` are `null` (not a fabricated "perfect 100" from `calculateScore([])`). `metadata.filtered_categories` lists profile exclusions; `metadata.skipped_checks` is reserved for runtime failures. `metadata.partial` stays `false` for profile-filtered audits. Server-side fix shipped in PR #375; this release gets it onto the npm-published CLI output path.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **SDK upgraded to `@vertaaux/sdk@2.0.0`** — Updated to match v2 API surface with snake_case parameter conventions.
|
|
25
|
+
- **Machine-mode hardening** — Payload output routes consistently through the data writer; enveloped JSON input is unwrapped uniformly across `baseline`, `comment`, and `diff` commands.
|
|
26
|
+
|
|
8
27
|
## [0.5.0] - 2026-03-19
|
|
9
28
|
|
|
10
29
|
### Added
|
package/README.md
CHANGED
|
@@ -119,11 +119,27 @@ All AI commands require authentication (`vertaa login` or `VERTAAUX_API_KEY`). T
|
|
|
119
119
|
| `upload <file>` | Upload audit results to cloud storage |
|
|
120
120
|
| `download <id>` | Download audit results from cloud storage |
|
|
121
121
|
|
|
122
|
+
### Accessibility
|
|
123
|
+
|
|
124
|
+
| Command | Description |
|
|
125
|
+
|---------|-------------|
|
|
126
|
+
| `a11y <url>` | Multi-engine accessibility audit (axe-core + AccessLint + custom analyzers) |
|
|
127
|
+
|
|
128
|
+
The `a11y` command uses a dedicated API endpoint (`/v1/a11y/audit`) and returns WCAG-mapped findings with structured fix suggestions and fixability ratings.
|
|
129
|
+
|
|
130
|
+
| Option | Description |
|
|
131
|
+
|--------|-------------|
|
|
132
|
+
| `--mode <basic\|standard\|deep>` | Audit depth (default: `basic`) |
|
|
133
|
+
| `--min-impact <minor\|moderate\|serious\|critical>` | Minimum impact level to report |
|
|
134
|
+
| `--fail-on-score <0-100>` | Exit 1 if accessibility score below this value |
|
|
135
|
+
| `--fail-on-findings <n>` | Exit 1 if critical+serious findings exceed n |
|
|
136
|
+
| `--format <json\|md>` | Output format (default: `json`) |
|
|
137
|
+
| `--timeout <ms>` | Wait timeout (default: 60000) |
|
|
138
|
+
|
|
122
139
|
### Aliases
|
|
123
140
|
|
|
124
141
|
| Command | Alias For |
|
|
125
142
|
|---------|-----------|
|
|
126
|
-
| `a11y <url>` | Accessibility-focused audit (filters for a11y issues) |
|
|
127
143
|
| `scan <url>` | UX scan (alias for audit) |
|
|
128
144
|
| `compare <urlA> <urlB>` | Compare audits of two URLs (also supports `--before`/`--after` for LLM-powered comparison) |
|
|
129
145
|
|
|
@@ -134,6 +150,7 @@ Formats are **per-command**, not global. Each command supports a different set o
|
|
|
134
150
|
| Command | Formats | Default |
|
|
135
151
|
|---------|---------|---------|
|
|
136
152
|
| `audit` | `human`, `json`, `sarif`, `junit`, `html` | `human` |
|
|
153
|
+
| `a11y` | `json`, `md` | `json` |
|
|
137
154
|
| `comment` | `json`, `markdown` | `markdown` |
|
|
138
155
|
| `explain` | `human`, `json` | `human` |
|
|
139
156
|
| `policy show` | `json`, `yaml` | `yaml` |
|
|
@@ -419,6 +436,16 @@ vertaa error: invalid value for --mode
|
|
|
419
436
|
│ valid: basic, standard, deep
|
|
420
437
|
```
|
|
421
438
|
|
|
439
|
+
## AI Agent Skill
|
|
440
|
+
|
|
441
|
+
Teach your AI coding agent (Claude Code, Cursor, Codex, Copilot, Gemini CLI, etc.) how to use the VertaaUX CLI:
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
npx skills add VertaaUX/agent-skills
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
Covers all CLI commands, CI/CD setup, SDK integration, and 10 use-case playbooks. Published on [skills.sh](https://skills.sh/VertaaUX/agent-skills).
|
|
448
|
+
|
|
422
449
|
## Related
|
|
423
450
|
|
|
424
451
|
- [Migration Guide](./MIGRATION.md) -- Breaking changes in this release
|
|
@@ -37,6 +37,8 @@ export declare class InteractiveApp {
|
|
|
37
37
|
private frameIndex;
|
|
38
38
|
private version;
|
|
39
39
|
private resolveRun;
|
|
40
|
+
/** Saved menu view so we can restore it after help overlay */
|
|
41
|
+
private savedMenuView;
|
|
40
42
|
constructor(output?: NodeJS.WritableStream);
|
|
41
43
|
/**
|
|
42
44
|
* Start the interactive app.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-app.d.ts","sourceRoot":"","sources":["../../src/app/interactive-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAa,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"interactive-app.d.ts","sourceRoot":"","sources":["../../src/app/interactive-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAa,MAAM,YAAY,CAAC;AAYnE;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,yDAAyD;IACzD,MAAM,EAAE,QAAQ,CAId;IAEF;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAS;IAExB,sCAAsC;IACtC,UAAU,UAAS;IAEnB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAA6B;IAC/C,8DAA8D;IAC9D,OAAO,CAAC,aAAa,CAA4B;gBAErC,MAAM,GAAE,MAAM,CAAC,cAA+B;IAQ1D;;;;;;OAMG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB1B;;;;OAIG;IACH,UAAU,IAAI,MAAM;IA6BpB;;;;;;OAMG;IACH,MAAM,IAAI,IAAI;IAMd;;;;;;;;OAQG;IACG,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/C;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAUhC;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAsBf;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAoBd;;OAEG;IACH,OAAO,IAAI,IAAI;IAgCf,8EAA8E;IAC9E,aAAa,IAAI,MAAM;IAMvB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,QAAQ,CAWd;IAEF,OAAO,CAAC,SAAS,CAmDf;CACH"}
|
|
@@ -17,6 +17,7 @@ import { renderHeader } from "./layout/header.js";
|
|
|
17
17
|
import { renderFooter } from "./layout/footer.js";
|
|
18
18
|
import { renderCanvas } from "./layout/canvas.js";
|
|
19
19
|
import { getVersion } from "../ui/banner.js";
|
|
20
|
+
import { HelpOverlayView } from "./views/help-overlay.js";
|
|
20
21
|
// Default keyboard shortcuts shown in the footer when no view is active
|
|
21
22
|
const DEFAULT_SHORTCUTS = ["↑↓ navigate", "↵ select", "F1 help", "^C quit"];
|
|
22
23
|
// Shortcuts shown when a command view is active
|
|
@@ -49,6 +50,8 @@ export class InteractiveApp {
|
|
|
49
50
|
frameIndex = 0;
|
|
50
51
|
version;
|
|
51
52
|
resolveRun = null;
|
|
53
|
+
/** Saved menu view so we can restore it after help overlay */
|
|
54
|
+
savedMenuView = null;
|
|
52
55
|
constructor(output = process.stderr) {
|
|
53
56
|
this.output = output;
|
|
54
57
|
this.version = getVersion();
|
|
@@ -273,7 +276,29 @@ export class InteractiveApp {
|
|
|
273
276
|
const key = data.toString();
|
|
274
277
|
const ctrl = key.length === 1 && data[0] < 32 && data[0] !== 27;
|
|
275
278
|
const meta = key.startsWith("\x1b") && key.length > 1;
|
|
276
|
-
//
|
|
279
|
+
// F1 is always handled at app level (before view delegation)
|
|
280
|
+
if (key === "\x1bOP" || key === "\x1b[11~") {
|
|
281
|
+
if (this._state.screen === "help") {
|
|
282
|
+
// Restore saved view
|
|
283
|
+
this._state.activeView = this.savedMenuView;
|
|
284
|
+
this.savedMenuView = null;
|
|
285
|
+
this._state.screen = "menu";
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
// Save current view and show help overlay
|
|
289
|
+
this.savedMenuView = this._state.activeView;
|
|
290
|
+
this._state.activeView = new HelpOverlayView(() => {
|
|
291
|
+
this._state.activeView = this.savedMenuView;
|
|
292
|
+
this.savedMenuView = null;
|
|
293
|
+
this._state.screen = "menu";
|
|
294
|
+
this.redraw();
|
|
295
|
+
});
|
|
296
|
+
this._state.screen = "help";
|
|
297
|
+
}
|
|
298
|
+
this.redraw();
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
// Delegate to active view
|
|
277
302
|
if (this._state.activeView?.handleKey) {
|
|
278
303
|
const consumed = this._state.activeView.handleKey(key, ctrl, meta);
|
|
279
304
|
if (consumed)
|
|
@@ -293,12 +318,6 @@ export class InteractiveApp {
|
|
|
293
318
|
process.exit(0);
|
|
294
319
|
}
|
|
295
320
|
}
|
|
296
|
-
else if (key === "\x1bOP" || key === "\x1b[11~") {
|
|
297
|
-
// F1 — toggle help
|
|
298
|
-
const next = this._state.screen === "help" ? "menu" : "help";
|
|
299
|
-
this._state.screen = next;
|
|
300
|
-
this.redraw();
|
|
301
|
-
}
|
|
302
321
|
else if (key === "\x1b" || key === "\x1b[") {
|
|
303
322
|
// Escape or Escape sequence
|
|
304
323
|
if (this._state.screen === "command" || this._state.screen === "help") {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Command category definitions for the interactive menu.
|
|
3
3
|
*
|
|
4
|
-
* 6 groups of
|
|
4
|
+
* 6 groups of 23 interactive-safe commands matching the TUI runner.
|
|
5
5
|
* Each MenuItem.value must exactly match the Commander command name.
|
|
6
6
|
*/
|
|
7
7
|
import type { CommandCategory, MenuItem } from "../types.js";
|
|
8
8
|
/**
|
|
9
|
-
* All
|
|
9
|
+
* All interactive-safe commands organized into 6 semantic groups.
|
|
10
10
|
*
|
|
11
11
|
* Groups follow a natural user workflow:
|
|
12
12
|
* Audit → Results → Fixes → Reports → Project → Account
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../../src/app/menu/categories.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../../src/app/menu/categories.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAAe,EAkJ/C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,IAAI,QAAQ,EAAE,CAEzC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Command category definitions for the interactive menu.
|
|
3
3
|
*
|
|
4
|
-
* 6 groups of
|
|
4
|
+
* 6 groups of 23 interactive-safe commands matching the TUI runner.
|
|
5
5
|
* Each MenuItem.value must exactly match the Commander command name.
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
|
-
* All
|
|
8
|
+
* All interactive-safe commands organized into 6 semantic groups.
|
|
9
9
|
*
|
|
10
10
|
* Groups follow a natural user workflow:
|
|
11
11
|
* Audit → Results → Fixes → Reports → Project → Account
|
|
@@ -84,11 +84,6 @@ export const COMMAND_CATEGORIES = [
|
|
|
84
84
|
value: "fix-plan",
|
|
85
85
|
description: "Generate a structured remediation plan",
|
|
86
86
|
},
|
|
87
|
-
{
|
|
88
|
-
name: "Review Patch",
|
|
89
|
-
value: "patch-review",
|
|
90
|
-
description: "Review a generated patch before applying",
|
|
91
|
-
},
|
|
92
87
|
],
|
|
93
88
|
},
|
|
94
89
|
{
|
|
@@ -104,11 +99,6 @@ export const COMMAND_CATEGORIES = [
|
|
|
104
99
|
value: "comment",
|
|
105
100
|
description: "Add audit annotations to source code",
|
|
106
101
|
},
|
|
107
|
-
{
|
|
108
|
-
name: "Release Notes",
|
|
109
|
-
value: "release-notes",
|
|
110
|
-
description: "Generate release notes from audit improvements",
|
|
111
|
-
},
|
|
112
102
|
],
|
|
113
103
|
},
|
|
114
104
|
{
|
|
@@ -134,11 +124,6 @@ export const COMMAND_CATEGORIES = [
|
|
|
134
124
|
value: "download",
|
|
135
125
|
description: "Download audit results from VertaaUX cloud",
|
|
136
126
|
},
|
|
137
|
-
{
|
|
138
|
-
name: "Verify Quality Gate",
|
|
139
|
-
value: "verify",
|
|
140
|
-
description: "Check if results meet quality gate thresholds",
|
|
141
|
-
},
|
|
142
127
|
],
|
|
143
128
|
},
|
|
144
129
|
{
|
|
@@ -160,7 +145,7 @@ export const COMMAND_CATEGORIES = [
|
|
|
160
145
|
description: "Show currently authenticated account",
|
|
161
146
|
},
|
|
162
147
|
{
|
|
163
|
-
name: "Health Check",
|
|
148
|
+
name: "Health Check (doctor)",
|
|
164
149
|
value: "doctor",
|
|
165
150
|
description: "Run diagnostics on CLI configuration and connectivity",
|
|
166
151
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-runner.d.ts","sourceRoot":"","sources":["../../../src/app/views/command-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"command-runner.d.ts","sourceRoot":"","sources":["../../../src/app/views/command-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAaH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAsH5D,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAa;IAG7B,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,WAAW,CAAM;IAGzB,OAAO,CAAC,oBAAoB,CAA6B;IAGzD,OAAO,CAAC,cAAc,CAAwB;IAG9C,OAAO,CAAC,YAAY,CAAgB;IAGpC,OAAO,CAAC,YAAY,CAAK;gBAGvB,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE,MAAM,IAAI;IAStB,MAAM,IAAI,MAAM;IA0EhB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;IAsFxD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YA+BhB,cAAc;CA4G7B"}
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Each command's handler is called directly (no program.parse()).
|
|
13
13
|
*/
|
|
14
|
+
import fs from "fs";
|
|
15
|
+
import path from "path";
|
|
14
16
|
import { dim, bold, colorize, brand, renderError, setRendererOverride, setKeyboardOverrideActive, renderStepList, getTerminalWidth, getTerminalHeight, } from "@vertaaux/tui";
|
|
15
17
|
import { setOutputBuffer } from "../../output/envelope.js";
|
|
16
18
|
// Command handler imports
|
|
@@ -38,6 +40,17 @@ import { handleVerify } from "../../commands/verify.js";
|
|
|
38
40
|
import { handleLogin, handleLogout, handleWhoami } from "../../commands/login.js";
|
|
39
41
|
import { handleDoctor } from "../../commands/doctor.js";
|
|
40
42
|
import { handlePolicy } from "../../commands/policy.js";
|
|
43
|
+
function resolveJobOrFile(value) {
|
|
44
|
+
const trimmed = value.trim();
|
|
45
|
+
const resolved = path.resolve(process.cwd(), trimmed);
|
|
46
|
+
if (trimmed.toLowerCase().endsWith(".json") ||
|
|
47
|
+
trimmed.includes("/") ||
|
|
48
|
+
trimmed.includes("\\") ||
|
|
49
|
+
fs.existsSync(resolved)) {
|
|
50
|
+
return { file: trimmed };
|
|
51
|
+
}
|
|
52
|
+
return { job: trimmed };
|
|
53
|
+
}
|
|
41
54
|
/**
|
|
42
55
|
* Get the argument definitions for a command.
|
|
43
56
|
*/
|
|
@@ -49,10 +62,24 @@ function getArgDefs(cmd) {
|
|
|
49
62
|
return [{ label: "Target URL", key: "url" }];
|
|
50
63
|
case "status":
|
|
51
64
|
return [{ label: "Job ID", key: "jobId" }];
|
|
65
|
+
case "diff":
|
|
66
|
+
case "triage":
|
|
67
|
+
case "explain":
|
|
68
|
+
case "fix-plan":
|
|
69
|
+
case "doc":
|
|
70
|
+
case "baseline":
|
|
71
|
+
return [{ label: "Audit job ID or JSON file", key: "auditSource" }];
|
|
72
|
+
case "compare":
|
|
73
|
+
return [
|
|
74
|
+
{ label: "URL A", key: "urlA" },
|
|
75
|
+
{ label: "URL B", key: "urlB" },
|
|
76
|
+
];
|
|
52
77
|
case "fix":
|
|
53
78
|
return [{ label: "Job ID to fix", key: "jobId" }];
|
|
54
79
|
case "suggest":
|
|
55
80
|
return [{ label: "Describe the fix you need", key: "intent" }];
|
|
81
|
+
case "comment":
|
|
82
|
+
return [{ label: "Audit JSON file", key: "input" }];
|
|
56
83
|
case "fix-all":
|
|
57
84
|
return [
|
|
58
85
|
{ label: "Job ID", key: "jobId" },
|
|
@@ -261,7 +288,7 @@ export class CommandRunnerView {
|
|
|
261
288
|
});
|
|
262
289
|
}
|
|
263
290
|
// Set overrides so command handlers use our canvas renderer,
|
|
264
|
-
// don't steal stdin, and buffer their output instead of writing to
|
|
291
|
+
// don't steal stdin, and buffer their output instead of writing to stdout.
|
|
265
292
|
this.status = "running";
|
|
266
293
|
setRendererOverride(this.canvasRenderer);
|
|
267
294
|
setKeyboardOverrideActive(true);
|
|
@@ -312,28 +339,39 @@ export class CommandRunnerView {
|
|
|
312
339
|
});
|
|
313
340
|
break;
|
|
314
341
|
case "diff":
|
|
315
|
-
await handleDiff(
|
|
342
|
+
await handleDiff(args.auditSource
|
|
343
|
+
? (() => {
|
|
344
|
+
const source = resolveJobOrFile(args.auditSource);
|
|
345
|
+
return source.file
|
|
346
|
+
? { fromFile: source.file }
|
|
347
|
+
: { jobIdArg: source.job };
|
|
348
|
+
})()
|
|
349
|
+
: {});
|
|
316
350
|
break;
|
|
317
351
|
case "compare":
|
|
318
|
-
await handleCompare({
|
|
352
|
+
await handleCompare({
|
|
353
|
+
urlA: args.urlA,
|
|
354
|
+
urlB: args.urlB,
|
|
355
|
+
wait: true,
|
|
356
|
+
});
|
|
319
357
|
break;
|
|
320
358
|
case "triage":
|
|
321
|
-
await handleTriage(
|
|
359
|
+
await handleTriage(resolveJobOrFile(args.auditSource));
|
|
322
360
|
break;
|
|
323
361
|
case "explain":
|
|
324
|
-
await handleExplain(
|
|
362
|
+
await handleExplain(resolveJobOrFile(args.auditSource));
|
|
325
363
|
break;
|
|
326
364
|
case "fix-plan":
|
|
327
|
-
await handleFixPlan(
|
|
365
|
+
await handleFixPlan(resolveJobOrFile(args.auditSource));
|
|
328
366
|
break;
|
|
329
367
|
case "patch-review":
|
|
330
368
|
await handlePatchReview({});
|
|
331
369
|
break;
|
|
332
370
|
case "doc":
|
|
333
|
-
await handleDoc(
|
|
371
|
+
await handleDoc(resolveJobOrFile(args.auditSource));
|
|
334
372
|
break;
|
|
335
373
|
case "comment":
|
|
336
|
-
await handleComment({});
|
|
374
|
+
await handleComment({ input: args.input });
|
|
337
375
|
break;
|
|
338
376
|
case "release-notes":
|
|
339
377
|
await handleReleaseNotes({});
|
|
@@ -342,7 +380,12 @@ export class CommandRunnerView {
|
|
|
342
380
|
await handleInit({});
|
|
343
381
|
break;
|
|
344
382
|
case "baseline":
|
|
345
|
-
await
|
|
383
|
+
await (() => {
|
|
384
|
+
const source = resolveJobOrFile(args.auditSource);
|
|
385
|
+
return source.file
|
|
386
|
+
? handleBaseline(undefined, { fromFile: source.file })
|
|
387
|
+
: handleBaseline(source.job, {});
|
|
388
|
+
})();
|
|
346
389
|
break;
|
|
347
390
|
case "upload":
|
|
348
391
|
await handleUpload(undefined, {});
|
|
@@ -15,7 +15,7 @@ export declare class HelpOverlayView implements CommandView {
|
|
|
15
15
|
constructor(onDismiss: () => void);
|
|
16
16
|
/** Render the help overlay as a box */
|
|
17
17
|
render(): string;
|
|
18
|
-
/** Handle
|
|
18
|
+
/** Handle Esc to dismiss the overlay (F1 toggle handled at app level) */
|
|
19
19
|
handleKey(key: string, _ctrl: boolean, _meta: boolean): boolean;
|
|
20
20
|
}
|
|
21
21
|
//# sourceMappingURL=help-overlay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-overlay.d.ts","sourceRoot":"","sources":["../../../src/app/views/help-overlay.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;gBAE3B,SAAS,EAAE,MAAM,IAAI;IAIjC,uCAAuC;IACvC,MAAM,IAAI,MAAM;IAehB,
|
|
1
|
+
{"version":3,"file":"help-overlay.d.ts","sourceRoot":"","sources":["../../../src/app/views/help-overlay.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;gBAE3B,SAAS,EAAE,MAAM,IAAI;IAIjC,uCAAuC;IACvC,MAAM,IAAI,MAAM;IAehB,yEAAyE;IACzE,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;CAQhE"}
|
|
@@ -11,7 +11,7 @@ const DEFAULT_SHORTCUTS = [
|
|
|
11
11
|
["Enter", "Select / confirm"],
|
|
12
12
|
["/", "Start search (or type any character)"],
|
|
13
13
|
["Esc", "Clear search / go back"],
|
|
14
|
-
["
|
|
14
|
+
["F1", "Toggle this help overlay"],
|
|
15
15
|
["Ctrl+C", "Exit vertaa"],
|
|
16
16
|
];
|
|
17
17
|
/**
|
|
@@ -34,12 +34,13 @@ export class HelpOverlayView {
|
|
|
34
34
|
].join("\n");
|
|
35
35
|
return box(content, { padding: 1 });
|
|
36
36
|
}
|
|
37
|
-
/** Handle
|
|
37
|
+
/** Handle Esc to dismiss the overlay (F1 toggle handled at app level) */
|
|
38
38
|
handleKey(key, _ctrl, _meta) {
|
|
39
|
-
if (key === "
|
|
39
|
+
if (key === "\x1b") {
|
|
40
40
|
this.onDismiss();
|
|
41
41
|
return true;
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
// Consume all other keys while overlay is visible
|
|
44
|
+
return true;
|
|
44
45
|
}
|
|
45
46
|
}
|
package/dist/commands/a11y.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* Runs
|
|
2
|
+
* A11y command handler.
|
|
3
|
+
* Runs a dedicated multi-engine accessibility audit via POST /v1/a11y/audit.
|
|
4
|
+
* Uses axe-core (101 WCAG rules) + @accesslint/core (structured fixes) + custom analyzers.
|
|
4
5
|
*/
|
|
5
6
|
import type { Command } from "commander";
|
|
6
7
|
import type { Flags } from "../types.js";
|
|
8
|
+
export declare function runA11yAudit(base: string, url: string, flags: Flags): Promise<void>;
|
|
7
9
|
export declare function handleA11y(rawUrl: string, cmdOptions: Flags): Promise<void>;
|
|
8
10
|
export declare function registerA11yCommand(program: Command): void;
|
|
9
11
|
//# sourceMappingURL=a11y.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../../src/commands/a11y.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../../src/commands/a11y.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAqEzC,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,IAAI,CAAC,CAkDf;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDjF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0B1D"}
|
package/dist/commands/a11y.js
CHANGED
|
@@ -1,12 +1,82 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* Runs
|
|
2
|
+
* A11y command handler.
|
|
3
|
+
* Runs a dedicated multi-engine accessibility audit via POST /v1/a11y/audit.
|
|
4
|
+
* Uses axe-core (101 WCAG rules) + @accesslint/core (structured fixes) + custom analyzers.
|
|
4
5
|
*/
|
|
5
6
|
import { renderError, runSteps, createRenderer } from "@vertaaux/tui";
|
|
6
7
|
import { ExitCode } from "../utils/exit-codes.js";
|
|
7
8
|
import { parseMode, parseTimeout, parseInterval, parseScore } from "../utils/validators.js";
|
|
8
|
-
import { resolveApiBase } from "../utils/api-client.js";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveApiBase, getString, getNumber, resolveFormat, } from "../utils/api-client.js";
|
|
10
|
+
import { apiRequest, getApiKey } from "../utils/client.js";
|
|
11
|
+
import { printOutput } from "../utils/formatters.js";
|
|
12
|
+
function formatA11yMarkdown(result) {
|
|
13
|
+
const lines = [
|
|
14
|
+
`## Accessibility Audit: ${result.url}`,
|
|
15
|
+
"",
|
|
16
|
+
`**Total findings:** ${result.total_findings}`,
|
|
17
|
+
`**Severity:** ${result.severity_counts.critical || 0} critical, ${result.severity_counts.serious || 0} serious, ${result.severity_counts.moderate || 0} moderate, ${result.severity_counts.minor || 0} minor`,
|
|
18
|
+
];
|
|
19
|
+
if (result.tier_shaping) {
|
|
20
|
+
lines.push("", `> ${result.tier_shaping.gated_findings} additional findings available on a paid plan.`, `> Upgrade: ${result.tier_shaping.upgrade_url}`);
|
|
21
|
+
}
|
|
22
|
+
if (result.findings.length > 0) {
|
|
23
|
+
lines.push("", "### Findings", "");
|
|
24
|
+
for (const f of result.findings.slice(0, 20)) {
|
|
25
|
+
const wcag = f.wcagCriteria?.length ? ` [WCAG ${f.wcagCriteria.join(", ")}]` : "";
|
|
26
|
+
lines.push(`- **[${f.impact.toUpperCase()}]** \`${f.engineId}/${f.ruleId}\`${wcag}`);
|
|
27
|
+
lines.push(` ${f.message}`);
|
|
28
|
+
lines.push(` Element: \`${f.selector}\``);
|
|
29
|
+
if (f.fix?.suggestion) {
|
|
30
|
+
lines.push(` Fix: ${f.fix.suggestion}`);
|
|
31
|
+
}
|
|
32
|
+
else if (f.fix?.attribute) {
|
|
33
|
+
lines.push(` Fix: ${f.fix.type} ${f.fix.attribute}="${f.fix.value || ""}"`);
|
|
34
|
+
}
|
|
35
|
+
if (f.fixability) {
|
|
36
|
+
lines.push(` Fixability: ${f.fixability}`);
|
|
37
|
+
}
|
|
38
|
+
lines.push("");
|
|
39
|
+
}
|
|
40
|
+
if (result.findings.length > 20) {
|
|
41
|
+
lines.push(`... and ${result.findings.length - 20} more findings.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
}
|
|
46
|
+
export async function runA11yAudit(base, url, flags) {
|
|
47
|
+
const minImpact = getString(flags, "min-impact");
|
|
48
|
+
const mode = getString(flags, "mode");
|
|
49
|
+
const format = resolveFormat(flags);
|
|
50
|
+
const apiKey = getApiKey();
|
|
51
|
+
const body = { url, source: "cli" };
|
|
52
|
+
if (minImpact)
|
|
53
|
+
body.min_impact = minImpact;
|
|
54
|
+
if (mode)
|
|
55
|
+
body.mode = mode;
|
|
56
|
+
const result = await apiRequest(base, "/a11y/audit", { method: "POST", body }, apiKey);
|
|
57
|
+
// Compute an accessibility score from findings for --fail-on-score
|
|
58
|
+
// Starts at 100, subtracts 15 per critical, 10 per serious, 5 per moderate, 2 per minor
|
|
59
|
+
const counts = result.severity_counts;
|
|
60
|
+
const a11yScore = Math.max(0, 100 -
|
|
61
|
+
(counts.critical || 0) * 15 -
|
|
62
|
+
(counts.serious || 0) * 10 -
|
|
63
|
+
(counts.moderate || 0) * 5 -
|
|
64
|
+
(counts.minor || 0) * 2);
|
|
65
|
+
printOutput(format, { ...result, accessibility_score: a11yScore }, formatA11yMarkdown(result));
|
|
66
|
+
// Exit non-zero if --fail-on-score and computed score is below threshold
|
|
67
|
+
const failOnScore = getNumber(flags, "fail-on-score");
|
|
68
|
+
if (failOnScore !== undefined && a11yScore < failOnScore) {
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
}
|
|
71
|
+
// Exit non-zero if --fail-on-findings and critical/serious findings exceed threshold
|
|
72
|
+
const failOnFindings = getNumber(flags, "fail-on-findings");
|
|
73
|
+
if (failOnFindings !== undefined) {
|
|
74
|
+
const criticalAndSerious = (counts.critical || 0) + (counts.serious || 0);
|
|
75
|
+
if (criticalAndSerious > failOnFindings) {
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
10
80
|
export async function handleA11y(rawUrl, cmdOptions) {
|
|
11
81
|
const url = /^https?:\/\//i.test(rawUrl) ? rawUrl : `https://${rawUrl}`;
|
|
12
82
|
const renderer = createRenderer("auto");
|
|
@@ -27,11 +97,11 @@ export async function handleA11y(rawUrl, cmdOptions) {
|
|
|
27
97
|
const steps = [
|
|
28
98
|
{
|
|
29
99
|
id: "a11y",
|
|
30
|
-
actionText: "Running accessibility audit...",
|
|
100
|
+
actionText: "Running multi-engine accessibility audit...",
|
|
31
101
|
summaryText: "Accessibility audit complete",
|
|
32
102
|
run: async () => {
|
|
33
103
|
const base = resolveApiBase(cmdOptions);
|
|
34
|
-
await
|
|
104
|
+
await runA11yAudit(base, url, cmdOptions);
|
|
35
105
|
},
|
|
36
106
|
},
|
|
37
107
|
];
|
|
@@ -54,12 +124,15 @@ export async function handleA11y(rawUrl, cmdOptions) {
|
|
|
54
124
|
export function registerA11yCommand(program) {
|
|
55
125
|
program
|
|
56
126
|
.command("a11y <url>")
|
|
57
|
-
.description("Run
|
|
127
|
+
.description("Run multi-engine accessibility audit (axe-core + accesslint + custom analyzers)")
|
|
58
128
|
.option("--mode <mode>", "Audit depth: basic|standard|deep", parseMode, "basic")
|
|
59
|
-
.option("--
|
|
129
|
+
.option("--min-impact <level>", "Minimum impact level: minor|moderate|serious|critical")
|
|
130
|
+
.option("--fail-on-score <n>", "Exit non-zero if accessibility score below n (0-100)", parseScore)
|
|
131
|
+
.option("--fail-on-findings <n>", "Exit non-zero if critical+serious findings exceed n")
|
|
132
|
+
.option("--wait", "Wait for audit completion (default: true)")
|
|
60
133
|
.option("--timeout <ms>", "Wait timeout in milliseconds (1-300000)", parseTimeout, 60000)
|
|
61
134
|
.option("--interval <ms>", "Poll interval in milliseconds (1-300000)", parseInterval, 5000)
|
|
62
|
-
.option("--
|
|
135
|
+
.option("--format <fmt>", "Output format: json|md", "json")
|
|
63
136
|
.action(async (url, cmdOptions) => {
|
|
64
137
|
try {
|
|
65
138
|
await handleA11y(url, cmdOptions);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/audit/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AA+D7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/audit/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AA+D7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAwFtD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CA+Uf;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0P3D"}
|
|
@@ -29,13 +29,13 @@ import { normalizeIssues, filterBySeverity, filterByCategory } from "./filters.j
|
|
|
29
29
|
import { mapStatusToPhase, getOverallScoreFromResult, extractNumericScores, countTotalIssues } from "./scoring.js";
|
|
30
30
|
import { saveReproArtifacts, saveArtifactBundle } from "./artifacts.js";
|
|
31
31
|
import { outputFireAndForget, outputFormattedResults, outputQualityGateResult } from "./output.js";
|
|
32
|
-
import { loadAndResolvePolicy, buildQualityGateConfig } from "./policy.js";
|
|
32
|
+
import { loadAndResolvePolicy, buildQualityGateConfig, resolveAuditProfile } from "./policy.js";
|
|
33
33
|
import { runInlineExplanation } from "./explain.js";
|
|
34
34
|
/**
|
|
35
35
|
* Apply filters, evaluate quality gate, and output results after audit completes.
|
|
36
36
|
*/
|
|
37
37
|
async function runPostAuditAnalysis(params) {
|
|
38
|
-
const { result, createdJobId, targetUrl, format, formatter, groupBy, options, config, interactive, quiet } = params;
|
|
38
|
+
const { result, createdJobId, targetUrl, format, formatter, groupBy, options, config, interactive, quiet, profile } = params;
|
|
39
39
|
// Save repro artifacts if requested
|
|
40
40
|
if (createdJobId) {
|
|
41
41
|
saveReproArtifacts(createdJobId, result, options, quiet);
|
|
@@ -49,8 +49,8 @@ async function runPostAuditAnalysis(params) {
|
|
|
49
49
|
const filteredResult = { ...result, issues };
|
|
50
50
|
// Load and apply policy (CICD-17)
|
|
51
51
|
await loadAndResolvePolicy(options, quiet);
|
|
52
|
-
// Build quality gate config and evaluate
|
|
53
|
-
const gateConfig = buildQualityGateConfig(config, options);
|
|
52
|
+
// Build quality gate config and evaluate (profile applied between config and CLI flags)
|
|
53
|
+
const gateConfig = buildQualityGateConfig(config, options, profile);
|
|
54
54
|
const baselinePath = options.baseline || config.baseline?.path;
|
|
55
55
|
const baseline = baselinePath ? await loadBaseline(baselinePath) : null;
|
|
56
56
|
const prLabels = detectPRLabels();
|
|
@@ -114,8 +114,10 @@ export async function handleAudit(rawUrl, options, config) {
|
|
|
114
114
|
process.exitCode = ExitCode.ERROR;
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
|
-
// Resolve
|
|
118
|
-
const
|
|
117
|
+
// Resolve audit profile (bundles categories, weights, thresholds, mode)
|
|
118
|
+
const profile = resolveAuditProfile(options.profile || config.profile, config.profiles);
|
|
119
|
+
// Resolve options with precedence: flags > config > profile > defaults
|
|
120
|
+
const mode = options.mode || config.mode || profile?.mode || "basic";
|
|
119
121
|
const timeout = options.timeout || config.timeout || 60000;
|
|
120
122
|
const interval = options.interval || config.interval || 5000;
|
|
121
123
|
const wait = options.wait ?? true; // Default to waiting for completion
|
|
@@ -219,8 +221,29 @@ export async function handleAudit(rawUrl, options, config) {
|
|
|
219
221
|
createdJobId = created.job_id;
|
|
220
222
|
}
|
|
221
223
|
else {
|
|
222
|
-
// Public URL — send to cloud API
|
|
223
|
-
|
|
224
|
+
// Public URL — send to cloud API.
|
|
225
|
+
//
|
|
226
|
+
// When the resolved profile declares a `categories` subset, we bypass
|
|
227
|
+
// `sdkClient.audits.create` and POST directly via `apiRequest`
|
|
228
|
+
// because the published @vertaaux/sdk typings don't yet include the
|
|
229
|
+
// `categories` field (Phase 1.5 wire format). The wire format is
|
|
230
|
+
// identical to the SDK's — same path, same auth — so this is a
|
|
231
|
+
// targeted escape hatch, not a fork. Once the SDK typings are bumped
|
|
232
|
+
// to include `categories?`, both branches collapse back to the SDK.
|
|
233
|
+
const profileCategories = profile?.categories;
|
|
234
|
+
const created = profileCategories && profileCategories.length > 0
|
|
235
|
+
? await apiRequest(base, "/audit", {
|
|
236
|
+
method: "POST",
|
|
237
|
+
body: {
|
|
238
|
+
url: targetUrl,
|
|
239
|
+
mode: mode,
|
|
240
|
+
categories: profileCategories,
|
|
241
|
+
},
|
|
242
|
+
}, apiKey)
|
|
243
|
+
: await sdkClient.audits.create({
|
|
244
|
+
url: targetUrl,
|
|
245
|
+
mode: mode,
|
|
246
|
+
});
|
|
224
247
|
auditResult = created;
|
|
225
248
|
createdJobId = created.job_id;
|
|
226
249
|
// If not waiting, just output the job info and stop processing.
|
|
@@ -352,6 +375,7 @@ export async function handleAudit(rawUrl, options, config) {
|
|
|
352
375
|
config,
|
|
353
376
|
interactive,
|
|
354
377
|
quiet,
|
|
378
|
+
profile,
|
|
355
379
|
});
|
|
356
380
|
}
|
|
357
381
|
}
|
|
@@ -415,6 +439,7 @@ export function registerAuditCommand(program) {
|
|
|
415
439
|
.option("--json-logs", "Output structured JSON logs for CI")
|
|
416
440
|
// Policy options (CICD-17)
|
|
417
441
|
.option("--policy <file>", "Path to policy file (default: auto-detect vertaa.policy.yml)")
|
|
442
|
+
.option("--profile <name>", "Audit profile: wcag-aa|conversion-focus|quick-ux|ci-gate|compliance")
|
|
418
443
|
.option("--explain", "Append AI explanation to audit results")
|
|
419
444
|
.option("--strict", "Fail immediately on first step error")
|
|
420
445
|
.option("--continue-on-error", "Continue on step errors even in CI")
|