@jevitate/cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/ai-cli.js +40 -30
- package/dist/ai-cli.js.map +1 -1
- package/dist/author-journey-cli.d.ts +4 -0
- package/dist/author-journey-cli.js +109 -0
- package/dist/author-journey-cli.js.map +1 -0
- package/dist/bin.js +58077 -22454
- package/dist/bin.js.map +1 -1
- package/dist/browser-run-options.d.ts +58 -0
- package/dist/browser-run-options.js +106 -0
- package/dist/browser-run-options.js.map +1 -0
- package/dist/build-info.generated.d.ts +2 -0
- package/dist/build-info.generated.js +10 -0
- package/dist/build-info.generated.js.map +1 -0
- package/dist/check-api.d.ts +5 -0
- package/dist/check-api.js +233 -0
- package/dist/check-api.js.map +1 -0
- package/dist/check-budget.d.ts +26 -0
- package/dist/check-budget.js +89 -0
- package/dist/check-budget.js.map +1 -0
- package/dist/check-cli.d.ts +31 -0
- package/dist/check-cli.js +109 -0
- package/dist/check-cli.js.map +1 -0
- package/dist/check-execute.d.ts +25 -0
- package/dist/check-execute.js +385 -0
- package/dist/check-execute.js.map +1 -0
- package/dist/check-plan.d.ts +113 -0
- package/dist/check-plan.js +448 -0
- package/dist/check-plan.js.map +1 -0
- package/dist/check-suite.d.ts +171 -0
- package/dist/check-suite.js +515 -0
- package/dist/check-suite.js.map +1 -0
- package/dist/check-types.d.ts +181 -0
- package/dist/check-types.js +35 -0
- package/dist/check-types.js.map +1 -0
- package/dist/cli-args.d.ts +26 -0
- package/dist/cli-args.js +50 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-output.d.ts +102 -0
- package/dist/cli-output.js +516 -0
- package/dist/cli-output.js.map +1 -0
- package/dist/cli-reference.d.ts +3 -0
- package/dist/cli-reference.js +81 -0
- package/dist/cli-reference.js.map +1 -0
- package/dist/cli-refusal.d.ts +12 -0
- package/dist/cli-refusal.js +52 -0
- package/dist/cli-refusal.js.map +1 -0
- package/dist/cli-shared.d.ts +330 -0
- package/dist/cli-shared.js +492 -0
- package/dist/cli-shared.js.map +1 -0
- package/dist/cli-surface.d.ts +33 -0
- package/dist/cli-surface.js +48 -0
- package/dist/cli-surface.js.map +1 -0
- package/dist/conversation-options.d.ts +15 -0
- package/dist/conversation-options.js +10 -0
- package/dist/conversation-options.js.map +1 -0
- package/dist/credentials-file.d.ts +15 -0
- package/dist/credentials-file.js +56 -0
- package/dist/credentials-file.js.map +1 -0
- package/dist/data-dir.d.ts +1 -1
- package/dist/data-dir.js +1 -1
- package/dist/defect-evidence.d.ts +141 -0
- package/dist/defect-evidence.js +502 -0
- package/dist/defect-evidence.js.map +1 -0
- package/dist/demo-aspect-api.d.ts +209 -0
- package/dist/demo-aspect-api.js +397 -0
- package/dist/demo-aspect-api.js.map +1 -0
- package/dist/demo-aspect-cli.d.ts +3 -0
- package/dist/demo-aspect-cli.js +241 -0
- package/dist/demo-aspect-cli.js.map +1 -0
- package/dist/demo-capture.d.ts +108 -0
- package/dist/demo-capture.js +438 -0
- package/dist/demo-capture.js.map +1 -0
- package/dist/engine.d.ts +35 -0
- package/dist/engine.js +25 -0
- package/dist/engine.js.map +1 -0
- package/dist/environments.d.ts +155 -0
- package/dist/environments.js +364 -0
- package/dist/environments.js.map +1 -0
- package/dist/exit-codes.d.ts +46 -0
- package/dist/exit-codes.js +91 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/explore-adversarial.d.ts +137 -0
- package/dist/explore-adversarial.js +218 -0
- package/dist/explore-adversarial.js.map +1 -0
- package/dist/explore-api.d.ts +7 -187
- package/dist/explore-api.js +7 -301
- package/dist/explore-api.js.map +1 -1
- package/dist/explore-author.d.ts +79 -0
- package/dist/explore-author.js +86 -0
- package/dist/explore-author.js.map +1 -0
- package/dist/explore-cli.d.ts +7 -0
- package/dist/explore-cli.js +963 -0
- package/dist/explore-cli.js.map +1 -0
- package/dist/explore-coverage.d.ts +158 -0
- package/dist/explore-coverage.js +240 -0
- package/dist/explore-coverage.js.map +1 -0
- package/dist/explore-feature.d.ts +127 -0
- package/dist/explore-feature.js +220 -0
- package/dist/explore-feature.js.map +1 -0
- package/dist/explore-goal.d.ts +253 -0
- package/dist/explore-goal.js +374 -0
- package/dist/explore-goal.js.map +1 -0
- package/dist/explore-shared.d.ts +152 -0
- package/dist/explore-shared.js +129 -0
- package/dist/explore-shared.js.map +1 -0
- package/dist/explore-specs.d.ts +53 -0
- package/dist/explore-specs.js +333 -0
- package/dist/explore-specs.js.map +1 -0
- package/dist/findings-filing.d.ts +64 -0
- package/dist/findings-filing.js +108 -0
- package/dist/findings-filing.js.map +1 -0
- package/dist/fixture-auth.d.ts +52 -0
- package/dist/fixture-auth.js +82 -0
- package/dist/fixture-auth.js.map +1 -0
- package/dist/fixture-cli.d.ts +70 -0
- package/dist/fixture-cli.js +178 -0
- package/dist/fixture-cli.js.map +1 -0
- package/dist/github-issue-filer.d.ts +62 -0
- package/dist/github-issue-filer.js +188 -0
- package/dist/github-issue-filer.js.map +1 -0
- package/dist/host-health-run.d.ts +24 -0
- package/dist/host-health-run.js +27 -0
- package/dist/host-health-run.js.map +1 -0
- package/dist/http-5xx-outcome.d.ts +6 -0
- package/dist/http-5xx-outcome.js +39 -0
- package/dist/http-5xx-outcome.js.map +1 -0
- package/dist/inbox-cli.d.ts +7 -0
- package/dist/inbox-cli.js +197 -0
- package/dist/inbox-cli.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init-cli.d.ts +4 -0
- package/dist/init-cli.js +127 -0
- package/dist/init-cli.js.map +1 -0
- package/dist/init-keys.d.ts +19 -2
- package/dist/init-keys.js +15 -4
- package/dist/init-keys.js.map +1 -1
- package/dist/init-next-steps.d.ts +35 -0
- package/dist/init-next-steps.js +79 -0
- package/dist/init-next-steps.js.map +1 -0
- package/dist/invariants-file.d.ts +34 -0
- package/dist/invariants-file.js +68 -0
- package/dist/invariants-file.js.map +1 -0
- package/dist/invariants-validate.d.ts +30 -0
- package/dist/invariants-validate.js +105 -0
- package/dist/invariants-validate.js.map +1 -0
- package/dist/journey-annotate-api.d.ts +76 -0
- package/dist/journey-annotate-api.js +256 -0
- package/dist/journey-annotate-api.js.map +1 -0
- package/dist/journey-annotate-cli.d.ts +9 -0
- package/dist/journey-annotate-cli.js +179 -0
- package/dist/journey-annotate-cli.js.map +1 -0
- package/dist/journey-api.d.ts +79 -2
- package/dist/journey-api.js +136 -19
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.d.ts +4 -0
- package/dist/journey-cli.js +370 -0
- package/dist/journey-cli.js.map +1 -0
- package/dist/journey-demo-api.d.ts +112 -0
- package/dist/journey-demo-api.js +392 -0
- package/dist/journey-demo-api.js.map +1 -0
- package/dist/journey-demo-cli.d.ts +10 -0
- package/dist/journey-demo-cli.js +155 -0
- package/dist/journey-demo-cli.js.map +1 -0
- package/dist/kill-signal.d.ts +193 -0
- package/dist/kill-signal.js +284 -0
- package/dist/kill-signal.js.map +1 -0
- package/dist/launch-armed.d.ts +37 -0
- package/dist/launch-armed.js +31 -0
- package/dist/launch-armed.js.map +1 -0
- package/dist/ledger-api.d.ts +106 -0
- package/dist/ledger-api.js +237 -0
- package/dist/ledger-api.js.map +1 -0
- package/dist/ledger-cli.d.ts +18 -0
- package/dist/ledger-cli.js +107 -0
- package/dist/ledger-cli.js.map +1 -0
- package/dist/load-api.d.ts +29 -11
- package/dist/load-api.js +23 -15
- package/dist/load-api.js.map +1 -1
- package/dist/load-cli.d.ts +4 -0
- package/dist/load-cli.js +97 -0
- package/dist/load-cli.js.map +1 -0
- package/dist/log-correlation.d.ts +147 -0
- package/dist/log-correlation.js +325 -0
- package/dist/log-correlation.js.map +1 -0
- package/dist/log-lines.d.ts +131 -0
- package/dist/log-lines.js +389 -0
- package/dist/log-lines.js.map +1 -0
- package/dist/log-sources.d.ts +71 -0
- package/dist/log-sources.js +235 -0
- package/dist/log-sources.js.map +1 -0
- package/dist/logs-cli.d.ts +3 -0
- package/dist/logs-cli.js +51 -0
- package/dist/logs-cli.js.map +1 -0
- package/dist/logs-retention.d.ts +28 -0
- package/dist/logs-retention.js +84 -0
- package/dist/logs-retention.js.map +1 -0
- package/dist/mcp-api.d.ts +89 -1
- package/dist/mcp-api.js +472 -18
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-args.d.ts +38 -0
- package/dist/mcp-args.js +131 -0
- package/dist/mcp-args.js.map +1 -0
- package/dist/mcp-cli-bridge.d.ts +34 -0
- package/dist/mcp-cli-bridge.js +62 -0
- package/dist/mcp-cli-bridge.js.map +1 -0
- package/dist/mcp-cli-runner.d.ts +29 -0
- package/dist/mcp-cli-runner.js +44 -0
- package/dist/mcp-cli-runner.js.map +1 -0
- package/dist/mcp-cli-tools.d.ts +125 -0
- package/dist/mcp-cli-tools.js +680 -0
- package/dist/mcp-cli-tools.js.map +1 -0
- package/dist/mcp-paths.d.ts +28 -0
- package/dist/mcp-paths.js +76 -0
- package/dist/mcp-paths.js.map +1 -0
- package/dist/mission-actors.d.ts +40 -0
- package/dist/mission-actors.js +72 -0
- package/dist/mission-actors.js.map +1 -0
- package/dist/mission-api.d.ts +35 -0
- package/dist/mission-api.js +58 -2
- package/dist/mission-api.js.map +1 -1
- package/dist/mission-cli.d.ts +4 -0
- package/dist/mission-cli.js +247 -0
- package/dist/mission-cli.js.map +1 -0
- package/dist/mission-exit.d.ts +22 -0
- package/dist/mission-exit.js +26 -0
- package/dist/mission-exit.js.map +1 -0
- package/dist/mission-fixtures.d.ts +225 -0
- package/dist/mission-fixtures.js +828 -0
- package/dist/mission-fixtures.js.map +1 -0
- package/dist/mission-journal.d.ts +60 -0
- package/dist/mission-journal.js +115 -0
- package/dist/mission-journal.js.map +1 -0
- package/dist/mission-queue-cli.d.ts +10 -0
- package/dist/mission-queue-cli.js +198 -0
- package/dist/mission-queue-cli.js.map +1 -0
- package/dist/mission-queue-runner.d.ts +126 -0
- package/dist/mission-queue-runner.js +397 -0
- package/dist/mission-queue-runner.js.map +1 -0
- package/dist/multi-run-cli.d.ts +37 -0
- package/dist/multi-run-cli.js +110 -0
- package/dist/multi-run-cli.js.map +1 -0
- package/dist/multi-run.d.ts +339 -0
- package/dist/multi-run.js +619 -0
- package/dist/multi-run.js.map +1 -0
- package/dist/openrouter-call.d.ts +22 -0
- package/dist/openrouter-call.js +63 -0
- package/dist/openrouter-call.js.map +1 -0
- package/dist/profile-cli.d.ts +4 -0
- package/dist/profile-cli.js +57 -0
- package/dist/profile-cli.js.map +1 -0
- package/dist/program.d.ts +3 -75
- package/dist/program.js +119 -1921
- package/dist/program.js.map +1 -1
- package/dist/project-dir.d.ts +96 -0
- package/dist/project-dir.js +220 -0
- package/dist/project-dir.js.map +1 -0
- package/dist/record-api.d.ts +10 -6
- package/dist/record-api.js +39 -28
- package/dist/record-api.js.map +1 -1
- package/dist/record-cli.d.ts +4 -0
- package/dist/record-cli.js +64 -0
- package/dist/record-cli.js.map +1 -0
- package/dist/recording-cli.d.ts +4 -0
- package/dist/recording-cli.js +248 -0
- package/dist/recording-cli.js.map +1 -0
- package/dist/regression-api.d.ts +101 -0
- package/dist/regression-api.js +384 -5
- package/dist/regression-api.js.map +1 -1
- package/dist/regression-cli.d.ts +4 -0
- package/dist/regression-cli.js +232 -0
- package/dist/regression-cli.js.map +1 -0
- package/dist/report-api.d.ts +146 -0
- package/dist/report-api.js +430 -0
- package/dist/report-api.js.map +1 -0
- package/dist/report-cli.d.ts +12 -0
- package/dist/report-cli.js +147 -0
- package/dist/report-cli.js.map +1 -0
- package/dist/result-schema.d.ts +22 -0
- package/dist/result-schema.js +28 -0
- package/dist/result-schema.js.map +1 -0
- package/dist/run-index.d.ts +29 -0
- package/dist/run-index.js +70 -0
- package/dist/run-index.js.map +1 -0
- package/dist/run-screenshots.d.ts +123 -0
- package/dist/run-screenshots.js +229 -0
- package/dist/run-screenshots.js.map +1 -0
- package/dist/runtime-env.d.ts +8 -0
- package/dist/runtime-env.js +22 -0
- package/dist/runtime-env.js.map +1 -0
- package/dist/secret-args.d.ts +23 -0
- package/dist/secret-args.js +45 -0
- package/dist/secret-args.js.map +1 -0
- package/dist/serve-cli.d.ts +4 -0
- package/dist/serve-cli.js +95 -0
- package/dist/serve-cli.js.map +1 -0
- package/dist/server-log-verify.d.ts +34 -0
- package/dist/server-log-verify.js +115 -0
- package/dist/server-log-verify.js.map +1 -0
- package/dist/session-check.d.ts +14 -0
- package/dist/session-check.js +44 -0
- package/dist/session-check.js.map +1 -0
- package/dist/site-cli.d.ts +4 -0
- package/dist/site-cli.js +127 -0
- package/dist/site-cli.js.map +1 -0
- package/dist/site-gate-cli.d.ts +28 -0
- package/dist/site-gate-cli.js +58 -0
- package/dist/site-gate-cli.js.map +1 -0
- package/dist/source-api.js +18 -3
- package/dist/source-api.js.map +1 -1
- package/dist/source-cli.d.ts +4 -0
- package/dist/source-cli.js +284 -0
- package/dist/source-cli.js.map +1 -0
- package/dist/source-run-api.d.ts +27 -1
- package/dist/source-run-api.js +22 -11
- package/dist/source-run-api.js.map +1 -1
- package/dist/storage-state-snapshot.d.ts +50 -0
- package/dist/storage-state-snapshot.js +87 -0
- package/dist/storage-state-snapshot.js.map +1 -0
- package/dist/suite-explore-options.d.ts +289 -0
- package/dist/suite-explore-options.js +140 -0
- package/dist/suite-explore-options.js.map +1 -0
- package/dist/target-config.d.ts +109 -0
- package/dist/target-config.js +216 -0
- package/dist/target-config.js.map +1 -0
- package/dist/transcript-file.d.ts +12 -0
- package/dist/transcript-file.js +23 -0
- package/dist/transcript-file.js.map +1 -0
- package/dist/ui-api.d.ts +3 -0
- package/dist/ui-api.js +7 -1
- package/dist/ui-api.js.map +1 -1
- package/dist/usability-capture.d.ts +43 -0
- package/dist/usability-capture.js +326 -0
- package/dist/usability-capture.js.map +1 -0
- package/dist/usage-config.d.ts +36 -0
- package/dist/usage-config.js +114 -0
- package/dist/usage-config.js.map +1 -0
- package/dist/ux-api.d.ts +3 -75
- package/dist/ux-api.js +3 -220
- package/dist/ux-api.js.map +1 -1
- package/dist/ux-cli.d.ts +4 -0
- package/dist/ux-cli.js +102 -0
- package/dist/ux-cli.js.map +1 -0
- package/dist/ux-config.d.ts +29 -0
- package/dist/ux-config.js +103 -0
- package/dist/ux-config.js.map +1 -0
- package/dist/ux-evidence.d.ts +54 -0
- package/dist/ux-evidence.js +197 -0
- package/dist/ux-evidence.js.map +1 -0
- package/dist/ux-review.d.ts +112 -0
- package/dist/ux-review.js +151 -0
- package/dist/ux-review.js.map +1 -0
- package/dist/ux-usability.d.ts +238 -0
- package/dist/ux-usability.js +494 -0
- package/dist/ux-usability.js.map +1 -0
- package/dist/verify-fix-api.d.ts +173 -0
- package/dist/verify-fix-api.js +454 -0
- package/dist/verify-fix-api.js.map +1 -0
- package/dist/verify-fix-cli.d.ts +4 -0
- package/dist/verify-fix-cli.js +110 -0
- package/dist/verify-fix-cli.js.map +1 -0
- package/package.json +19 -14
- package/skills/jevitate-ci-check/SKILL.md +77 -0
- package/skills/jevitate-demo/SKILL.md +61 -0
- package/skills/jevitate-explore/SKILL.md +88 -87
- package/skills/jevitate-getting-started/SKILL.md +88 -0
- package/skills/jevitate-load-test/SKILL.md +11 -2
- package/skills/jevitate-mission-scope/SKILL.md +19 -11
- package/skills/jevitate-record/SKILL.md +23 -5
- package/skills/jevitate-run-journey/SKILL.md +61 -17
- package/skills/jevitate-sources/SKILL.md +57 -14
- package/skills/jevitate-ux-review/SKILL.md +106 -16
- package/skills/jevitate-verify-fix/SKILL.md +76 -0
package/dist/record-api.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { logsDirFor } from "./project-dir.js";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { assertAuthorizedExploreTarget, normalizeAllowlist } from "@jevitate/explore";
|
|
5
5
|
import { PlaywrightBrowserPort } from "@jevitate/playwright";
|
|
6
6
|
import { Recorder } from "@jevitate/recorder";
|
|
7
|
-
import { resolveDataDir } from "./data-dir.js";
|
|
8
7
|
export async function runRecording(opts) {
|
|
9
8
|
// Guardrail #1 — authorize BEFORE opening a browser. Throws on refusal.
|
|
10
9
|
const origin = assertAuthorizedExploreTarget(opts.url, opts.allowlist);
|
|
11
10
|
const portFactory = opts.browserPortFactory ?? (() => new PlaywrightBrowserPort());
|
|
12
11
|
const port = portFactory();
|
|
13
|
-
const profileDir = await mkdtemp(join(tmpdir(), "jevitate-record-"));
|
|
14
12
|
const session = await port.open({
|
|
15
|
-
profileDir,
|
|
16
13
|
headless: opts.headless ?? false,
|
|
17
14
|
allowedOrigins: [...opts.allowlist],
|
|
18
15
|
baseUrl: origin,
|
|
@@ -29,7 +26,7 @@ export async function runRecording(opts) {
|
|
|
29
26
|
await (opts.waitForStop ?? waitForEnterKey)();
|
|
30
27
|
const recording = await recorder.stop(opts.retro);
|
|
31
28
|
const finalUrl = session.page.url();
|
|
32
|
-
const outDir = opts.outDir ??
|
|
29
|
+
const outDir = opts.outDir ?? logsDirFor();
|
|
33
30
|
await mkdir(outDir, { recursive: true });
|
|
34
31
|
const iso = (opts.nowIso ?? (() => new Date().toISOString()))();
|
|
35
32
|
const recordingPath = join(outDir, `record-${iso.replace(/[:.]/g, "-")}.json`);
|
|
@@ -39,7 +36,6 @@ export async function runRecording(opts) {
|
|
|
39
36
|
}
|
|
40
37
|
finally {
|
|
41
38
|
await session.close();
|
|
42
|
-
await rm(profileDir, { recursive: true, force: true });
|
|
43
39
|
}
|
|
44
40
|
}
|
|
45
41
|
/**
|
|
@@ -54,39 +50,54 @@ export function resolveRecordAllowlist(url, allow) {
|
|
|
54
50
|
return normalizeAllowlist([url]);
|
|
55
51
|
}
|
|
56
52
|
/**
|
|
57
|
-
* The default stop signal for an interactive `jevitate record` session:
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
53
|
+
* The default stop signal for an interactive `jevitate record` session: resolves the first time
|
|
54
|
+
* the user presses Enter on stdin, OR on SIGINT (Ctrl-C, #124) — both end the take the SAME way,
|
|
55
|
+
* through `recorder.stop()` + the write to disk in `runRecording`'s normal path, so a take is
|
|
56
|
+
* never silently lost. SIGINT matters most for `--headless` (no visible window to interact with,
|
|
57
|
+
* so Ctrl-C is the natural way to signal "done"): registering a listener here means Node does NOT
|
|
58
|
+
* fall back to its default "kill the process" SIGINT behavior — the take is saved first.
|
|
59
|
+
* Best-effort on stdin — if it is not a TTY / not readable, resolves immediately rather than
|
|
60
|
+
* hanging the capture forever (SIGINT still works either way).
|
|
61
61
|
*/
|
|
62
62
|
export function waitForEnterKey() {
|
|
63
63
|
return new Promise((resolve) => {
|
|
64
|
+
let settled = false;
|
|
64
65
|
const stdin = process.stdin;
|
|
65
|
-
|
|
66
|
-
resolve();
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
66
|
+
const onSigint = () => finish();
|
|
69
67
|
const onData = (chunk) => {
|
|
70
|
-
if (chunk.includes(0x0a) || chunk.includes(0x0d))
|
|
71
|
-
|
|
72
|
-
resolve();
|
|
73
|
-
}
|
|
68
|
+
if (chunk.includes(0x0a) || chunk.includes(0x0d))
|
|
69
|
+
finish();
|
|
74
70
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
stdin.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
function cleanup() {
|
|
72
|
+
process.off("SIGINT", onSigint);
|
|
73
|
+
if (stdin && stdin.readable) {
|
|
74
|
+
stdin.off("data", onData);
|
|
75
|
+
try {
|
|
76
|
+
stdin.pause();
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// stdin may already be closed; nothing to pause.
|
|
80
|
+
}
|
|
82
81
|
}
|
|
83
|
-
}
|
|
82
|
+
}
|
|
83
|
+
function finish() {
|
|
84
|
+
if (settled)
|
|
85
|
+
return;
|
|
86
|
+
settled = true;
|
|
87
|
+
cleanup();
|
|
88
|
+
resolve();
|
|
89
|
+
}
|
|
90
|
+
process.on("SIGINT", onSigint);
|
|
91
|
+
if (!stdin || !stdin.readable) {
|
|
92
|
+
finish();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
84
95
|
try {
|
|
85
96
|
stdin.resume();
|
|
86
97
|
stdin.on("data", onData);
|
|
87
98
|
}
|
|
88
99
|
catch {
|
|
89
|
-
|
|
100
|
+
finish();
|
|
90
101
|
}
|
|
91
102
|
});
|
|
92
103
|
}
|
package/dist/record-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-api.js","sourceRoot":"","sources":["../src/record-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"record-api.js","sourceRoot":"","sources":["../src/record-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { UnauthorizedExploreTargetError } from "@jevitate/explore";
|
|
2
|
+
import { ok, fail } from "./envelope.js";
|
|
3
|
+
import { runRecording, resolveRecordAllowlist } from "./record-api.js";
|
|
4
|
+
import { emitJson } from "./cli-shared.js";
|
|
5
|
+
/** Registers `jevitate record` (record-by-demonstration). */
|
|
6
|
+
export function registerRecordCommands(program, deps) {
|
|
7
|
+
// Additive: `jevitate record` — record-by-demonstration (Ticket #22). Opens a
|
|
8
|
+
// real browser on an authorized origin, lets the user demonstrate a flow, and
|
|
9
|
+
// captures it into a schema-valid, replayable Recording written to disk. The
|
|
10
|
+
// authorized-origin guard is enforced FIRST (fail-closed) inside runRecording,
|
|
11
|
+
// before any browser is opened; the temp profile dir is always cleaned up.
|
|
12
|
+
program
|
|
13
|
+
.command("record")
|
|
14
|
+
.description("record a demonstrated flow into a Recording (authoring plane)")
|
|
15
|
+
.option("--url <url>", "start URL to demonstrate from (must be an authorized origin)")
|
|
16
|
+
.option("--intent <text>", "your framing of the journey (carried to Recording.intent)")
|
|
17
|
+
.option("--retro <text>", "optional retrospective note (carried to Recording.retro)")
|
|
18
|
+
.option("--allow <origin>", "authorized origin (repeatable); REPLACES the default allowlist when given (the URL's own origin is used only when --allow is omitted entirely) -- include the URL's own origin explicitly if you still need it", (v, prev) => [...prev, v], [])
|
|
19
|
+
.option("--headless", "run headless (default: headed — a record session is a live demonstration)", false)
|
|
20
|
+
.option("--out <dir>", "directory to write the emitted Recording (default: .jevitate/logs/<date> in the project, else ~/.jevitate/logs/<date>)")
|
|
21
|
+
.option("--json", "emit a JSON envelope")
|
|
22
|
+
.action(async function () {
|
|
23
|
+
const o = this.opts();
|
|
24
|
+
if (!o.url) {
|
|
25
|
+
emitJson(program, fail("E_RECORD_ARGS", "--url is required"));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const allowlist = resolveRecordAllowlist(o.url, o.allow);
|
|
29
|
+
try {
|
|
30
|
+
const result = await runRecording({
|
|
31
|
+
url: o.url,
|
|
32
|
+
allowlist,
|
|
33
|
+
intent: o.intent,
|
|
34
|
+
retro: o.retro,
|
|
35
|
+
outDir: o.out,
|
|
36
|
+
headless: o.headless ?? false,
|
|
37
|
+
browserPortFactory: deps.record?.browserPortFactory,
|
|
38
|
+
recorderFactory: deps.record?.recorderFactory,
|
|
39
|
+
waitForStop: deps.record?.waitForStop,
|
|
40
|
+
});
|
|
41
|
+
const summary = {
|
|
42
|
+
recordingPath: result.recordingPath,
|
|
43
|
+
steps: result.steps,
|
|
44
|
+
pages: result.pages,
|
|
45
|
+
finalUrl: result.finalUrl,
|
|
46
|
+
};
|
|
47
|
+
if (o.json) {
|
|
48
|
+
emitJson(program, ok(summary));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
program.configureOutput().writeOut?.(`${JSON.stringify(summary)}\n`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
if (err instanceof UnauthorizedExploreTargetError) {
|
|
56
|
+
emitJson(program, fail("E_UNAUTHORIZED_EXPLORE_TARGET", err.message));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
emitJson(program, fail("E_RECORD_RUN", String(err instanceof Error ? err.message : err)));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=record-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-cli.js","sourceRoot":"","sources":["../src/record-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import * as clack from "@clack/prompts";
|
|
3
|
+
import { RecordingSchema, AuthoringTakeSchema, PostdocDecisionsSchema, promoteToVariable, diffTakes, applyPostdoc, flattenBaseFillSteps, fitInteractionPolicy, } from "@jevitate/recording";
|
|
4
|
+
import { ok, fail } from "./envelope.js";
|
|
5
|
+
import { nonNegativeIntArg } from "./cli-args.js";
|
|
6
|
+
import { emitJson } from "./cli-shared.js";
|
|
7
|
+
/** Registers `jevitate recording`: `promote|diff|fit|postdoc`. */
|
|
8
|
+
export function registerRecordingCommands(program, deps) {
|
|
9
|
+
/**
|
|
10
|
+
* Reads one "take file" for `recording diff`/`recording postdoc` (#124): a JSON object written
|
|
11
|
+
* by `jevitate record` — `{ recording, values }` (`AuthoringTakeSchema`). A raw `Recording` — the
|
|
12
|
+
* kind `explore`/`explore-author-journey`/a usability run emits directly, `{version, site, pages,
|
|
13
|
+
* ...}` at the TOP level, no `recording`/`values` wrapper — is a common, easy mistake to hand
|
|
14
|
+
* here; `AuthoringTakeSchema`'s `.strict()` rejects it with an opaque `Unrecognized keys: version,
|
|
15
|
+
* site, intent, pages` zod dump. Detected BEFORE the schema parse so the caller gets a message
|
|
16
|
+
* that names the actual problem and how to fix it, not a zod dump.
|
|
17
|
+
*/
|
|
18
|
+
async function readAuthoringTake(file) {
|
|
19
|
+
const raw = await readFile(file, "utf8");
|
|
20
|
+
let json;
|
|
21
|
+
try {
|
|
22
|
+
json = JSON.parse(raw);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
throw new Error(`'${file}' is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
26
|
+
}
|
|
27
|
+
if (json !== null && typeof json === "object" && !Array.isArray(json) && "pages" in json && !("recording" in json)) {
|
|
28
|
+
throw new Error(`'${file}' looks like a Recording (it has a top-level "pages"), not a take file. ` +
|
|
29
|
+
`'recording diff'/'recording postdoc' need a take file written by 'jevitate record' — shape ` +
|
|
30
|
+
`{ recording, values } — not a raw Recording from 'explore', 'explore-author-journey', or a ` +
|
|
31
|
+
`usability run. Wrap it as { "recording": <the Recording>, "values": {} } if you want to ` +
|
|
32
|
+
`diff/postdoc it anyway.`);
|
|
33
|
+
}
|
|
34
|
+
const parsed = AuthoringTakeSchema.parse(json);
|
|
35
|
+
return { recording: parsed.recording, values: new Map(Object.entries(parsed.values)) };
|
|
36
|
+
}
|
|
37
|
+
const recording = program.command("recording").description("inspect and edit recorded takes (promote, edit steps, diff, postdoc)");
|
|
38
|
+
recording
|
|
39
|
+
.command("promote <file>")
|
|
40
|
+
.requiredOption("--page <n>", "page index", nonNegativeIntArg)
|
|
41
|
+
.requiredOption("--step <n>", "step index within the page", nonNegativeIntArg)
|
|
42
|
+
.requiredOption("--var <name>", "variable name to bind")
|
|
43
|
+
.action(async function (file) {
|
|
44
|
+
const { page, step, var: varName } = this.opts();
|
|
45
|
+
try {
|
|
46
|
+
const raw = await readFile(file, "utf8");
|
|
47
|
+
const rec = RecordingSchema.parse(JSON.parse(raw));
|
|
48
|
+
const result = promoteToVariable(rec, { page: Number(page), step: Number(step) }, varName);
|
|
49
|
+
program.configureOutput().writeOut?.(`${JSON.stringify(result, null, 2)}\n`);
|
|
50
|
+
process.exitCode = 0;
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
emitJson(program, fail("E_INVALID_RECORDING", String(err)));
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
recording
|
|
57
|
+
.command("diff <takeA> <takeB> [more...]")
|
|
58
|
+
.option("--json", "emit a JSON envelope")
|
|
59
|
+
.action(async function (takeA, takeB, more) {
|
|
60
|
+
const { json } = this.opts();
|
|
61
|
+
try {
|
|
62
|
+
const files = [takeA, takeB, ...more];
|
|
63
|
+
const takes = await Promise.all(files.map(readAuthoringTake));
|
|
64
|
+
const diffResult = diffTakes(takes);
|
|
65
|
+
const envelope = ok(diffResult);
|
|
66
|
+
if (json) {
|
|
67
|
+
emitJson(program, envelope);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const out = program.configureOutput().writeOut;
|
|
71
|
+
diffResult.columns.forEach((col, i) => {
|
|
72
|
+
const type = col.inferredType ? `, type=${col.inferredType}` : "";
|
|
73
|
+
out?.(`column ${i}: ${col.kind} (confidence ${col.confidence.toFixed(2)}${type}) values=${JSON.stringify(col.values)}\n`);
|
|
74
|
+
});
|
|
75
|
+
process.exitCode = 0;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
emitJson(program, fail("E_INVALID_TAKE", String(err)));
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
recording
|
|
83
|
+
.command("fit <file>")
|
|
84
|
+
.option("--json", "emit a JSON envelope")
|
|
85
|
+
.action(async function (file) {
|
|
86
|
+
const { json } = this.opts();
|
|
87
|
+
try {
|
|
88
|
+
const raw = await readFile(file, "utf8");
|
|
89
|
+
const rec = RecordingSchema.parse(JSON.parse(raw));
|
|
90
|
+
const interaction = fitInteractionPolicy(rec);
|
|
91
|
+
const policy = { version: "1.0.0", interaction };
|
|
92
|
+
if (json) {
|
|
93
|
+
emitJson(program, ok(policy));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
program.configureOutput().writeOut?.(`${JSON.stringify(policy, null, 2)}\n`);
|
|
97
|
+
process.exitCode = 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
emitJson(program, fail("E_INVALID_RECORDING", String(err)));
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
recording
|
|
105
|
+
.command("postdoc <take> [more...]")
|
|
106
|
+
.option("--decisions <file>", "path to a PostdocDecision[] JSON file (non-interactive mode)")
|
|
107
|
+
.option("--out <file>", "write the resulting Recording to this file instead of stdout")
|
|
108
|
+
.option("--json", "emit a JSON envelope")
|
|
109
|
+
.action(async function (take, more) {
|
|
110
|
+
const { decisions: decisionsFile, out, json } = this.opts();
|
|
111
|
+
try {
|
|
112
|
+
const files = [take, ...more];
|
|
113
|
+
const takes = await Promise.all(files.map(readAuthoringTake));
|
|
114
|
+
const diff = diffTakes(takes);
|
|
115
|
+
let decisions;
|
|
116
|
+
if (decisionsFile !== undefined) {
|
|
117
|
+
decisions = await loadDecisions(decisionsFile);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
decisions = await promptForDecisions(takes[0]);
|
|
121
|
+
}
|
|
122
|
+
const result = applyPostdoc(takes[0], diff, decisions);
|
|
123
|
+
if (out !== undefined) {
|
|
124
|
+
await writeFile(out, `${JSON.stringify(result, null, 2)}\n`, "utf8");
|
|
125
|
+
}
|
|
126
|
+
if (json) {
|
|
127
|
+
emitJson(program, ok(result));
|
|
128
|
+
}
|
|
129
|
+
else if (out === undefined) {
|
|
130
|
+
program.configureOutput().writeOut?.(`${JSON.stringify(result, null, 2)}\n`);
|
|
131
|
+
process.exitCode = 0;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
process.exitCode = 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
if (err instanceof DecisionsParseError) {
|
|
139
|
+
emitJson(program, fail("E_INVALID_DECISIONS", String(err.cause)));
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
emitJson(program, fail("E_INVALID_TAKE", String(err)));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Distinguishes a malformed `--decisions <file>` (E_INVALID_DECISIONS) from
|
|
149
|
+
* every other failure mode of the `postdoc` action (E_INVALID_TAKE) without
|
|
150
|
+
* making `loadDecisions` itself responsible for emitting the CLI envelope —
|
|
151
|
+
* matching this file's existing pattern of one try/catch per subcommand
|
|
152
|
+
* mapping to one error code.
|
|
153
|
+
*/
|
|
154
|
+
class DecisionsParseError extends Error {
|
|
155
|
+
cause;
|
|
156
|
+
constructor(cause) {
|
|
157
|
+
super(String(cause));
|
|
158
|
+
this.cause = cause;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function loadDecisions(file) {
|
|
162
|
+
let raw;
|
|
163
|
+
let parsed;
|
|
164
|
+
try {
|
|
165
|
+
raw = await readFile(file, "utf8");
|
|
166
|
+
parsed = JSON.parse(raw);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
throw new DecisionsParseError(err);
|
|
170
|
+
}
|
|
171
|
+
const result = PostdocDecisionsSchema.safeParse(parsed);
|
|
172
|
+
if (!result.success) {
|
|
173
|
+
throw new DecisionsParseError(result.error);
|
|
174
|
+
}
|
|
175
|
+
return result.data;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Thin `@clack/prompts` adapter: walks `authoring`'s fill/select steps in
|
|
179
|
+
* order and asks the human how to classify each one. ALL logic (variance
|
|
180
|
+
* guards, secret-materialization checks, the actual step rewrite) lives in
|
|
181
|
+
* `applyPostdoc`/`diffTakes` — this function only collects a
|
|
182
|
+
* `PostdocDecision[]` to hand them.
|
|
183
|
+
*/
|
|
184
|
+
async function promptForDecisions(authoring) {
|
|
185
|
+
clack.intro("recording postdoc — review captured fill/select steps");
|
|
186
|
+
const decisions = [];
|
|
187
|
+
const fillSteps = flattenBaseFillSteps(authoring.recording);
|
|
188
|
+
for (const { ref } of fillSteps) {
|
|
189
|
+
const classify = await clack.select({
|
|
190
|
+
message: `Step ${ref.page}:${ref.step} — how should this value be classified?`,
|
|
191
|
+
options: [
|
|
192
|
+
{ value: "constant", label: "constant", hint: "fix this value in the artifact" },
|
|
193
|
+
{ value: "variable", label: "variable", hint: "prompt for a value at replay time" },
|
|
194
|
+
{ value: "handback", label: "handback", hint: "hand control to a human at replay time" },
|
|
195
|
+
],
|
|
196
|
+
});
|
|
197
|
+
if (clack.isCancel(classify)) {
|
|
198
|
+
clack.cancel("postdoc review cancelled");
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
const label = await promptOptionalText("Label for this step? (blank to skip)");
|
|
202
|
+
const chunk = await promptOptionalText("Chunk name for this step? (blank to skip)");
|
|
203
|
+
let decision;
|
|
204
|
+
if (classify === "constant") {
|
|
205
|
+
const acknowledgeVaried = await clack.confirm({
|
|
206
|
+
message: "Acknowledge this value varied across takes anyway?",
|
|
207
|
+
initialValue: false,
|
|
208
|
+
});
|
|
209
|
+
if (clack.isCancel(acknowledgeVaried)) {
|
|
210
|
+
clack.cancel("postdoc review cancelled");
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
decision = { step: ref, classify: "constant", ...(acknowledgeVaried ? { acknowledgeVaried: true } : {}) };
|
|
214
|
+
}
|
|
215
|
+
else if (classify === "variable") {
|
|
216
|
+
const name = await clack.text({ message: "Variable name?" });
|
|
217
|
+
if (clack.isCancel(name)) {
|
|
218
|
+
clack.cancel("postdoc review cancelled");
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
decision = { step: ref, classify: "variable", name };
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
const prompt = await clack.text({ message: "Handback prompt for the human operator?" });
|
|
225
|
+
if (clack.isCancel(prompt)) {
|
|
226
|
+
clack.cancel("postdoc review cancelled");
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
decision = { step: ref, classify: "handback", prompt };
|
|
230
|
+
}
|
|
231
|
+
if (label !== undefined)
|
|
232
|
+
decision = { ...decision, label };
|
|
233
|
+
if (chunk !== undefined)
|
|
234
|
+
decision = { ...decision, chunk };
|
|
235
|
+
decisions.push(decision);
|
|
236
|
+
}
|
|
237
|
+
clack.outro("review complete");
|
|
238
|
+
return decisions;
|
|
239
|
+
}
|
|
240
|
+
async function promptOptionalText(message) {
|
|
241
|
+
const value = await clack.text({ message, defaultValue: "" });
|
|
242
|
+
if (clack.isCancel(value)) {
|
|
243
|
+
clack.cancel("postdoc review cancelled");
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
return value === "" ? undefined : value;
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=recording-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recording-cli.js","sourceRoot":"","sources":["../src/recording-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAExC,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,GAKrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAgB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEzD,kEAAkE;AAClE,MAAM,UAAU,yBAAyB,CAAC,OAAgB,EAAE,IAAa;IACvE;;;;;;;;OAQG;IACH,KAAK,UAAU,iBAAiB,CAAC,IAAY;QAC3C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,EAAE,CAAC;YACnH,MAAM,IAAI,KAAK,CACb,IAAI,IAAI,0EAA0E;gBAChF,6FAA6F;gBAC7F,6FAA6F;gBAC7F,0FAA0F;gBAC1F,yBAAyB,CAC5B,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;IACzF,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,sEAAsE,CAAC,CAAC;IAEnI,SAAS;SACN,OAAO,CAAC,gBAAgB,CAAC;SACzB,cAAc,CAAC,YAAY,EAAE,YAAY,EAAE,iBAAiB,CAAC;SAC7D,cAAc,CAAC,YAAY,EAAE,4BAA4B,EAAE,iBAAiB,CAAC;SAC7E,cAAc,CAAC,cAAc,EAAE,uBAAuB,CAAC;SACvD,MAAM,CAAC,KAAK,WAA0B,IAAY;QACjD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,EAA+C,CAAC;QAC9F,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACzC,MAAM,GAAG,GAAc,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAC3F,OAAO,CAAC,eAAe,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,SAAS;SACN,OAAO,CAAC,gCAAgC,CAAC;SACzC,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAAC;SACxC,MAAM,CAAC,KAAK,WAA0B,KAAa,EAAE,KAAa,EAAE,IAAc;QACjF,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,EAAsB,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;YACtC,MAAM,KAAK,GAAyB,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACpF,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC;YAChC,IAAI,IAAI,EAAE,CAAC;gBACT,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC;gBAC/C,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAgB,EAAE,CAAS,EAAE,EAAE;oBACzD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClE,GAAG,EAAE,CACH,UAAU,CAAC,KAAK,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,YAAY,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CACnH,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,SAAS;SACN,OAAO,CAAC,YAAY,CAAC;SACrB,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAAC;SACxC,MAAM,CAAC,KAAK,WAA0B,IAAY;QACjD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,EAAsB,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACzC,MAAM,GAAG,GAAc,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9D,MAAM,WAAW,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAe,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;YAC7D,IAAI,IAAI,EAAE,CAAC;gBACT,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,eAAe,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,SAAS;SACN,OAAO,CAAC,0BAA0B,CAAC;SACnC,MAAM,CAAC,oBAAoB,EAAE,8DAA8D,CAAC;SAC5F,MAAM,CAAC,cAAc,EAAE,8DAA8D,CAAC;SACtF,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAAC;SACxC,MAAM,CAAC,KAAK,WAA0B,IAAY,EAAE,IAAc;QACjE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,EAIrD,CAAC;QACL,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;YAC9B,MAAM,KAAK,GAAyB,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACpF,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YAE9B,IAAI,SAA4B,CAAC;YACjC,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBAChC,SAAS,GAAG,MAAM,aAAa,CAAC,aAAa,CAAC,CAAC;YACjD,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,CAAC;YAED,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;YAEvD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,MAAM,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,IAAI,EAAE,CAAC;gBACT,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC7B,OAAO,CAAC,eAAe,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;gBACvC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;;GAMG;AACH,MAAM,mBAAoB,SAAQ,KAAK;IACT;IAA5B,YAA4B,KAAc;QACxC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QADK,UAAK,GAAL,KAAK,CAAS;IAE1C,CAAC;CACF;AAED,KAAK,UAAU,aAAa,CAAC,IAAY;IACvC,IAAI,GAAW,CAAC;IAChB,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACnC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACxD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,kBAAkB,CAAC,SAA6B;IAC7D,KAAK,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAErE,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,MAAM,SAAS,GAAG,oBAAoB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAE5D,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,SAAS,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;YAClC,OAAO,EAAE,QAAQ,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,yCAAyC;YAC9E,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,UAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,gCAAgC,EAAE;gBACzF,EAAE,KAAK,EAAE,UAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,mCAAmC,EAAE;gBAC5F,EAAE,KAAK,EAAE,UAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,wCAAwC,EAAE;aAClG;SACF,CAAC,CAAC;QACH,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,sCAAsC,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,2CAA2C,CAAC,CAAC;QAEpF,IAAI,QAAyB,CAAC;QAC9B,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC5B,MAAM,iBAAiB,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBAC5C,OAAO,EAAE,oDAAoD;gBAC7D,YAAY,EAAE,KAAK;aACpB,CAAC,CAAC;YACH,IAAI,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACtC,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,QAAQ,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QACrH,CAAC;aAAM,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC7D,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,QAAQ,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;YACxF,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,QAAQ,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QACzD,CAAC;QAED,IAAI,KAAK,KAAK,SAAS;YAAE,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC3D,IAAI,KAAK,KAAK,SAAS;YAAE,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC3D,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC/B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,OAAe;IAC/C,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1C,CAAC"}
|
package/dist/regression-api.d.ts
CHANGED
|
@@ -1,4 +1,53 @@
|
|
|
1
1
|
import type { Actor } from "@jevitate/screenplay";
|
|
2
|
+
import { type ResolvedJourneyEnvironment } from "./environments.js";
|
|
3
|
+
import { type PersistedFinding } from "./verify-fix-api.js";
|
|
4
|
+
/** #213: `--id <id>` already names a committed regression — refused unless `--force`, checked
|
|
5
|
+
* BEFORE any reproduce/minimize attempt runs (never a browser-driven overwrite the caller didn't ask for). */
|
|
6
|
+
export declare class RegressionExistsError extends Error {
|
|
7
|
+
readonly code: "E_REGRESSION_EXISTS";
|
|
8
|
+
constructor(id: string, dir: string);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The clear, actionable refusal #81 requires: a Recording with no failure to
|
|
12
|
+
* reproduce is refused rather than "minimized" into a vacuous artifact that
|
|
13
|
+
* can only ever pass.
|
|
14
|
+
*/
|
|
15
|
+
export declare class NoFailureToReproduceError extends Error {
|
|
16
|
+
readonly code: "E_REGRESSION_NO_FAILURE";
|
|
17
|
+
constructor(message?: string);
|
|
18
|
+
}
|
|
19
|
+
/** `--result` was given but carries no usable oracle at all: no failed `--success` check (of ANY
|
|
20
|
+
* kind — page/reloadThen/requestMade/responseStatus), no matching declared-invariant defect, and no
|
|
21
|
+
* APP-caused failed-action step (jevitate's own engine refusals — #92's repeated-side-effect guard,
|
|
22
|
+
* a budget/fail-closed cutoff, … — are never a valid oracle; #119/#129). */
|
|
23
|
+
export declare class NoOracleInResultError extends Error {
|
|
24
|
+
readonly code: "E_REGRESSION_NO_ORACLE";
|
|
25
|
+
constructor(resultPath: string, detail: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* #213: `--fingerprint` names one of the mission's OWN findings, but a hard-signal one (http-5xx,
|
|
29
|
+
* hang, server-log, adversarial-misuse, … — everything but `invariant`, which `captureInvariantRegression`
|
|
30
|
+
* already handles). Its oracle is the signal itself, never a page/success-check assertion —
|
|
31
|
+
* `deriveOracle` (transcript/checks only) can never express it, so falling through to it just
|
|
32
|
+
* produces a generic "no usable oracle" that reads as the `--result` file being unusable, when the
|
|
33
|
+
* real answer is: this isn't the tool for it. Points at the route that IS: `ledger add` (repro
|
|
34
|
+
* material for `ledger verify` / `verify-fix`).
|
|
35
|
+
*/
|
|
36
|
+
export declare class RegressionHardSignalOracleError extends Error {
|
|
37
|
+
readonly code: "E_REGRESSION_HARD_SIGNAL";
|
|
38
|
+
constructor(resultPath: string, finding: PersistedFinding);
|
|
39
|
+
}
|
|
40
|
+
/** An explicit `--fingerprint` disagrees with the oracle derived from `--result`. */
|
|
41
|
+
export declare class FingerprintMismatchError extends Error {
|
|
42
|
+
readonly code: "E_REGRESSION_FINGERPRINT_MISMATCH";
|
|
43
|
+
constructor(given: string, derived: string);
|
|
44
|
+
}
|
|
45
|
+
/** An invariant defect matched by `--fingerprint`, but `verify-fix`'s own replay says it does not
|
|
46
|
+
* currently reproduce (fixed, or inconclusive) — never fabricated into a regression. */
|
|
47
|
+
export declare class InvariantNotReproducingError extends Error {
|
|
48
|
+
readonly code: "E_REGRESSION_INVARIANT_NOT_REPRODUCING";
|
|
49
|
+
constructor(invariantId: string, verdict: string, reason: string);
|
|
50
|
+
}
|
|
2
51
|
export interface RunRegressionCaptureOptions {
|
|
3
52
|
failingRecordingPath: string;
|
|
4
53
|
id: string;
|
|
@@ -6,6 +55,25 @@ export interface RunRegressionCaptureOptions {
|
|
|
6
55
|
attempts?: number;
|
|
7
56
|
bugSummary?: string;
|
|
8
57
|
makeActor: () => Promise<Actor>;
|
|
58
|
+
/**
|
|
59
|
+
* Path to a mission result JSON (what `jevitate explore` writes alongside its Recording as
|
|
60
|
+
* `<recording>.result.json`) — supplies a failure oracle (#81 item 2) when the Recording alone
|
|
61
|
+
* carries no reproducible failure, because the failing action itself was never captured as a
|
|
62
|
+
* step (see `@jevitate/explore`'s `RunRecorder`: only successful actions are recorded).
|
|
63
|
+
*/
|
|
64
|
+
resultPath?: string;
|
|
65
|
+
/**
|
|
66
|
+
* An explicit failure fingerprint. Accepts EITHER a `stepSignature` (see `@jevitate/regression`'s
|
|
67
|
+
* `fingerprintFailure`) alone pinning which structural step in `--from` counts as "the" failure,
|
|
68
|
+
* OR — combined with `--result` (#119/#129) — the SAME defect/invariant fingerprint every other
|
|
69
|
+
* command (`verify-fix`, the mission report) uses: when it matches one of the mission's OWN
|
|
70
|
+
* declared-invariant defects, that invariant is re-checked (via `verify-fix`'s own machinery)
|
|
71
|
+
* rather than turned into a Recording step. Combined with a page-checkable `--result` oracle, it
|
|
72
|
+
* cross-checks the derived oracle.
|
|
73
|
+
*/
|
|
74
|
+
fingerprint?: string;
|
|
75
|
+
/** #213: overwrite an existing `<id>.recording.json`/`.meta.json` — default: refused (fail closed). */
|
|
76
|
+
force?: boolean;
|
|
9
77
|
}
|
|
10
78
|
export type RunRegressionCaptureResult = {
|
|
11
79
|
recordingPath: string;
|
|
@@ -15,3 +83,36 @@ export type RunRegressionCaptureResult = {
|
|
|
15
83
|
rate: number;
|
|
16
84
|
};
|
|
17
85
|
export declare function runRegressionCapture(opts: RunRegressionCaptureOptions): Promise<RunRegressionCaptureResult>;
|
|
86
|
+
/** No committed `<id>.recording.json`/`<id>.meta.json` in the regressions directory. */
|
|
87
|
+
export declare class RegressionNotFoundError extends Error {
|
|
88
|
+
readonly code: "E_REGRESSION_NOT_FOUND";
|
|
89
|
+
constructor(id: string, dir: string);
|
|
90
|
+
}
|
|
91
|
+
export interface RunRegressionRunOptions {
|
|
92
|
+
readonly id: string;
|
|
93
|
+
readonly regressionsDir: string;
|
|
94
|
+
readonly makeActor: () => Promise<Actor>;
|
|
95
|
+
/** Fresh-context replays for a declared-invariant oracle (mirrors `verify-fix --replays`). Default 3. */
|
|
96
|
+
readonly attempts?: number;
|
|
97
|
+
/**
|
|
98
|
+
* #247 (`--env`/`--base-url`): replay against this environment — the committed Recording's
|
|
99
|
+
* same-origin URLs (and an invariant oracle's baseUrl/allowlist) move onto it; a step on an origin
|
|
100
|
+
* it does not allow is refused before any browser opens. Absent: the recorded site, as before.
|
|
101
|
+
*/
|
|
102
|
+
readonly environment?: ResolvedJourneyEnvironment;
|
|
103
|
+
}
|
|
104
|
+
export type RegressionRunVerdict = "reproduces" | "fixed" | "inconclusive" | "intermittent";
|
|
105
|
+
export interface RegressionRunReport {
|
|
106
|
+
readonly id: string;
|
|
107
|
+
readonly verdict: RegressionRunVerdict;
|
|
108
|
+
readonly reason: string;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* `regression run <id>` (#129 item 4): replays a committed regression and reports whether it still
|
|
112
|
+
* REPRODUCES or is now FIXED. Dispatches on `meta.oracle` — absent (the default/original) means the
|
|
113
|
+
* committed Recording's own trailing `assert` step IS the oracle, replayed by `@jevitate/regression`'s
|
|
114
|
+
* `replayRegression` (its `expect` failing/holding is the verdict, no different from any other
|
|
115
|
+
* `RecordingInterpreter` run); a `network`/`invariant` oracle is re-evaluated the SAME way capture
|
|
116
|
+
* established it (`replayAndCheckNetwork` / `verifyFix`'s invariant re-check) — never duplicated.
|
|
117
|
+
*/
|
|
118
|
+
export declare function runRegressionRun(opts: RunRegressionRunOptions): Promise<RegressionRunReport>;
|