aztrx-cli 0.4.2 → 0.4.3

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/README.md CHANGED
@@ -114,7 +114,7 @@ jobs:
114
114
  permissions: { contents: read, pull-requests: write }
115
115
  steps:
116
116
  - uses: actions/checkout@v4
117
- - uses: Aztrx-AI/aztrx@98dbad0f7b6681c7670f7068d01dc0d54813a55f
117
+ - uses: Aztrx-AI/aztrx@v0.4.3
118
118
  with:
119
119
  url: http://localhost:3000
120
120
  start-command: npm run dev # optional — boot the app in the background
@@ -137,9 +137,11 @@ niche tuning knobs).
137
137
  | --- | --- | --- |
138
138
  | `--fuzz` | Seeded chaos fuzzing instead of the deterministic walk | — |
139
139
  | `--http-fuzz` | Server-side mutation fuzzing — hostile requests against the target origin | — |
140
+ | `--http-fuzz-mutations` | With `--http-fuzz`: also send POST/PUT body mutations (default: GET-only) | — |
140
141
  | `--repro` | Minimize (ddmin) → emit Playwright spec → validate flake rate | — |
141
142
  | `--heal` | Generate + verify a fix (implies `--repro`) | — |
142
143
  | `--fix` | Find → explain → heal → apply — the one-command fix (free for null/undefined derefs) | — |
144
+ | `--magic-fix` | Hidden alias for `--fix` (deprecated) | — |
143
145
  | `--explain` | Print a human-language summary of the findings | — |
144
146
  | `--yes` / `-y` | Auto-apply verified fixes without prompting (with `--fix`) | — |
145
147
  | `--pr` | Open a merge-ready PR with the verified fixes (with `--fix`) | — |
@@ -150,10 +152,10 @@ niche tuning knobs).
150
152
  | `--max-actions <n>` | Max actions per pass | `100` |
151
153
  | `--seed <n>` | PRNG seed for deterministic fuzz | `42` |
152
154
  | `--workers <n>` | Number of parallel detection workers | `1` |
153
- | `--swarm` | Hidden alias for `--workers auto` | — |
155
+ | `--swarm` | Auto-size the swarm to CPU cores (capped at 8) | — |
154
156
  | `--repro-runs <n>` | Flake-rate replay iterations | `3` |
155
157
  | `--heal-model <model>` | Fallback LLM tier | `claude-sonnet-5` / `$AZTRX_MODEL` |
156
- | `--heal-fast-model <model>` | Fast/cheap first tier | `claude-haiku-4-5` / `$AZTRX_FAST_MODEL` |
158
+ | `--heal-fast-model <model>` | Fast/cheap first tier | `claude-haiku-4-5-20251001` / `$AZTRX_FAST_MODEL` |
157
159
  | `--test-command <cmd>` | Test command run against a healed patch | `npm test` (auto-detected) |
158
160
  | `--test-timeout <ms>` | Timeout for the heal test gate | `300000` |
159
161
  | `--no-test` | Skip the test gate during healing | — |
@@ -166,7 +168,11 @@ niche tuning knobs).
166
168
  | `--repo <path>` | Root path for sourcemap → source resolution | cwd |
167
169
  | `--allow-host <host>` | Add a host to the network allow-list (repeatable) | — |
168
170
  | `--storage-state <path>` | Playwright storage-state for authenticated pages | — |
171
+ | `--auth <path>` | Hidden alias for `--storage-state` | — |
169
172
  | `--login` | Auto-login before the pass (needs `AZTRX_AUTH_EMAIL`/`AZTRX_AUTH_PASSWORD`) | — |
173
+ | `--login-email <email>` | Email for `--login` (default: `$AZTRX_AUTH_EMAIL`) | — |
174
+ | `--login-password <pass>` | Password for `--login` (default: `$AZTRX_AUTH_PASSWORD`) | — |
175
+ | `--login-url <url>` | Explicit login page URL for `--login` (default: current page) | — |
170
176
  | `--fail-on` | Exit `1` if any crash/error finding is present | — |
171
177
  | `--dry-run` | Log planned actions without executing them | — |
172
178
  | `--crash-test` | Throw a deliberate error to verify capture | — |
@@ -182,7 +188,7 @@ Every run writes self-contained artifacts inside `.aztrx/` (gitignored):
182
188
  .aztrx/
183
189
  ├── report.html # interactive triage report
184
190
  ├── repro/<id>.spec.ts # minimal, executable Playwright repro
185
- ├── heal/fix.patch # gated, compiler-checked fix
191
+ ├── heal/<id>.patch # gated, compiler-checked fix (one per finding)
186
192
  ├── events.jsonl # run log (streamed by `aztrx-cli studio`)
187
193
  ├── pr-comment.md # GitHub PR markdown (with --pr-comment)
188
194
  └── badge.svg # status badge (with --badge)
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Chromium launcher with a first-run safety net. Playwright no longer downloads
3
+ * its browser builds on `npm install`, so a fresh `npx aztrx-cli run` would
4
+ * otherwise die on a bare "Executable doesn't exist". This detects that specific
5
+ * failure, installs the Chromium build that matches the bundled Playwright
6
+ * version, and retries once — keeping the zero-setup promise.
7
+ */
8
+ import { spawn } from "child_process";
9
+ import { createRequire } from "module";
10
+ import path from "path";
11
+ import pc from "picocolors";
12
+ import { chromium } from "playwright";
13
+ const require = createRequire(import.meta.url);
14
+ /** True when the driver can't find its browser build (the "run playwright install" case). */
15
+ function isMissingBrowser(err) {
16
+ const msg = err instanceof Error ? err.message : String(err);
17
+ return /Executable doesn't exist|playwright install/i.test(msg);
18
+ }
19
+ /** Install the Chromium build that matches the bundled Playwright version. */
20
+ function installChromium() {
21
+ const pkgPath = require.resolve("playwright/package.json");
22
+ const cli = path.join(path.dirname(pkgPath), "cli.js");
23
+ return new Promise((resolve, reject) => {
24
+ const child = spawn(process.execPath, [cli, "install", "chromium"], {
25
+ stdio: ["ignore", "pipe", "pipe"],
26
+ });
27
+ // Route progress to stderr so it never corrupts the Ink TUI on stdout.
28
+ child.stdout?.on("data", (d) => process.stderr.write(d));
29
+ child.stderr?.on("data", (d) => process.stderr.write(d));
30
+ child.on("error", reject);
31
+ child.on("close", (code) => code === 0 ? resolve() : reject(new Error(`playwright install exited ${code}`)));
32
+ });
33
+ }
34
+ /** Launch Chromium headlessly, installing its browser build first when absent. */
35
+ export async function launchChromium(options = {}) {
36
+ const launch = () => chromium.launch({ headless: true, ...options });
37
+ try {
38
+ return await launch();
39
+ }
40
+ catch (err) {
41
+ if (!isMissingBrowser(err))
42
+ throw err;
43
+ process.stderr.write(pc.dim("First run: downloading the Chromium browser (~150 MB)…\n"));
44
+ await installChromium();
45
+ return await launch();
46
+ }
47
+ }
@@ -1,5 +1,5 @@
1
- import { chromium } from "playwright";
2
1
  import { EventBus } from "./eventBus.js";
2
+ import { launchChromium } from "./browser.js";
3
3
  import { attachInterceptor } from "./interceptor.js";
4
4
  import { fingerprintOf } from "./classifier.js";
5
5
  /** Replays a recorded action sequence against a page. Best-effort: a selector
@@ -79,7 +79,7 @@ export class ReplayEngine {
79
79
  }
80
80
  async getBrowser() {
81
81
  if (!this.browser)
82
- this.browser = await chromium.launch({ headless: true });
82
+ this.browser = await launchChromium();
83
83
  return this.browser;
84
84
  }
85
85
  async run(url, actions, targetFingerprint, opts) {
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import * as fs from "fs";
13
13
  import * as path from "path";
14
- import { chromium } from "playwright";
14
+ import { launchChromium } from "./browser.js";
15
15
  import { EventBus } from "./eventBus.js";
16
16
  import { attachInterceptor } from "./interceptor.js";
17
17
  import { establishLogin } from "./auth.js";
@@ -211,7 +211,7 @@ function strategyLabel(s) {
211
211
  /** Launch one browser, run the worker roster concurrently, merge findings. */
212
212
  export async function swarmDetect(opts) {
213
213
  const strategies = buildStrategies(opts);
214
- const browser = await chromium.launch({ headless: true });
214
+ const browser = await launchChromium();
215
215
  try {
216
216
  const settled = await Promise.allSettled(strategies.map((strategy, i) => detectWorker(browser, {
217
217
  url: opts.url,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aztrx-cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "private": false,
5
5
  "description": "Aztrx AI — runtime stress-tester for web apps. Detect bugs, then prove them with an executable repro.",
6
6
  "license": "Apache-2.0",
@@ -48,7 +48,7 @@
48
48
  "commander": "^12.1.0",
49
49
  "ink": "^5.2.0",
50
50
  "picocolors": "^1.1.1",
51
- "playwright": "^1.49.0",
51
+ "playwright": "1.62.1",
52
52
  "react": "^18.3.1",
53
53
  "typescript": "^5.7.0"
54
54
  },