@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/load-api.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
1
|
import { FsJourneyStore, JourneyRegistry, deriveParamSchema, validateParams } from "@jevitate/journey";
|
|
2
|
+
import { gateJourney } from "./site-gate-cli.js";
|
|
5
3
|
import { safeRunPolicy } from "@jevitate/domain";
|
|
6
4
|
import { PlaywrightBrowserPort } from "@jevitate/playwright";
|
|
5
|
+
import { sessionLaunchOptions } from "./browser-run-options.js";
|
|
7
6
|
import { CastActor, BrowseTheWeb } from "@jevitate/screenplay";
|
|
8
7
|
import { RecordingInterpreter } from "@jevitate/interpreter";
|
|
9
8
|
import { JourneyRunner } from "@jevitate/runtime";
|
|
10
9
|
import { runLoadTest } from "@jevitate/load";
|
|
10
|
+
import { JourneyRequiresAuthError } from "./journey-api.js";
|
|
11
|
+
import { applyJourneyEnvironment } from "./environments.js";
|
|
11
12
|
/** Distinct from `@jevitate/journey`'s ParamValidationError-style "unknown id" cases elsewhere, so CLI callers can branch without string-matching. */
|
|
12
13
|
export class UnknownLoadJourneyError extends Error {
|
|
13
14
|
}
|
|
@@ -21,18 +22,25 @@ export class UnknownLoadJourneyError extends Error {
|
|
|
21
22
|
*
|
|
22
23
|
* NOTE on "seeded ⇒ reproducible / human-paced" (corrected post-review):
|
|
23
24
|
* `opts.seed` makes the ACTOR POOL's composition reproducible (via
|
|
24
|
-
* `deriveActorSeeds` inside `runLoadTest`) —
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* `deriveActorSeeds` inside `runLoadTest`), and — with a site policy that declares pacing — each
|
|
26
|
+
* actor's clicks and keystrokes are human-paced, seeded from `seed` and the actor's index. A load
|
|
27
|
+
* run is the operator's deliberate burst: the policy's throttles, budgets and quiet hours do not
|
|
28
|
+
* refuse it; only its pacing applies.
|
|
28
29
|
*/
|
|
29
30
|
export async function runJourneyLoadTest(opts) {
|
|
30
31
|
const store = new FsJourneyStore(opts.dir);
|
|
31
32
|
const registry = new JourneyRegistry(store);
|
|
32
|
-
const
|
|
33
|
-
if (!
|
|
33
|
+
const stored = await registry.get(opts.id);
|
|
34
|
+
if (!stored) {
|
|
34
35
|
throw new UnknownLoadJourneyError(`unknown journey '${opts.id}'`);
|
|
35
36
|
}
|
|
37
|
+
const journey = applyJourneyEnvironment(stored, opts.environment);
|
|
38
|
+
const allowedOrigins = opts.environment === undefined ? [journey.recording.site] : [...opts.environment.allowedOrigins];
|
|
39
|
+
// #118: a Journey that declares it needs auth refuses BEFORE any browser launch when no
|
|
40
|
+
// storageState was given — a clear, typed failure instead of a deep `replay-target-not-found`.
|
|
41
|
+
if (journey.metadata.requiresAuth === true && opts.storageState === undefined) {
|
|
42
|
+
throw new JourneyRequiresAuthError(`journey '${opts.id}' requires auth (metadata.requiresAuth) — run with --storage-state <file>`);
|
|
43
|
+
}
|
|
36
44
|
validateParams(deriveParamSchema(journey.recording), opts.params);
|
|
37
45
|
const policy = opts.policy ?? safeRunPolicy();
|
|
38
46
|
const browserPortFactory = opts.browserPortFactory ?? (() => new PlaywrightBrowserPort());
|
|
@@ -43,15 +51,16 @@ export async function runJourneyLoadTest(opts) {
|
|
|
43
51
|
iterationsPerActor: opts.iterationsPerActor,
|
|
44
52
|
seed: opts.seed,
|
|
45
53
|
runnerFactory: async (actorIndex) => {
|
|
46
|
-
const profileDir = await mkdtemp(join(tmpdir(), `doit-load-actor-${actorIndex}-`));
|
|
47
54
|
const port = browserPortFactory();
|
|
48
55
|
const session = await port.open({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
allowedOrigins: [journey.recording.site],
|
|
56
|
+
...sessionLaunchOptions(opts.browser),
|
|
57
|
+
allowedOrigins,
|
|
52
58
|
baseUrl: journey.recording.site,
|
|
59
|
+
...opts.emulation,
|
|
60
|
+
...(opts.storageState !== undefined ? { storageState: opts.storageState } : {}),
|
|
53
61
|
});
|
|
54
|
-
const
|
|
62
|
+
const gate = await gateJourney(opts.siteGate, journey.recording, { enforceLimits: false, runId: `load-${opts.seed}-${actorIndex}` });
|
|
63
|
+
const actor = CastActor.named(`load-actor-${actorIndex}`).whoCan(new BrowseTheWeb(session, allowedOrigins), ...gate.abilities);
|
|
55
64
|
const runner = new JourneyRunner(actor, new RecordingInterpreter());
|
|
56
65
|
// `runLoadTest` calls `run()` exactly `iterationsPerActor` times for
|
|
57
66
|
// this actor — success or failure, never more, never fewer (see
|
|
@@ -73,7 +82,6 @@ export async function runJourneyLoadTest(opts) {
|
|
|
73
82
|
remainingIterations--;
|
|
74
83
|
if (remainingIterations <= 0) {
|
|
75
84
|
await session.close();
|
|
76
|
-
await rm(profileDir, { recursive: true, force: true });
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
87
|
},
|
package/dist/load-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-api.js","sourceRoot":"","sources":["../src/load-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"load-api.js","sourceRoot":"","sources":["../src/load-api.ts"],"names":[],"mappings":"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"}
|
package/dist/load-cli.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { ok, fail } from "./envelope.js";
|
|
3
|
+
import { JourneyRequiresAuthError } from "./journey-api.js";
|
|
4
|
+
import { runJourneyLoadTest, UnknownLoadJourneyError } from "./load-api.js";
|
|
5
|
+
import { withSiteGate } from "./site-gate-cli.js";
|
|
6
|
+
import { withEngine } from "./engine.js";
|
|
7
|
+
import { finiteNumberArg, positiveIntArg } from "./cli-args.js";
|
|
8
|
+
import { environmentFromFlags, isEnvironmentError, withEnvironmentFlags } from "./environments.js";
|
|
9
|
+
import { resolveDbPath, resolveJourneysDir, withBrowserLaunchFlags, browserOption, withEmulationFlags, emulationFromFlags, collectParam, emitJson, environmentSeams, } from "./cli-shared.js";
|
|
10
|
+
/** Registers `jevitate load run`. */
|
|
11
|
+
export function registerLoadCommands(program, deps) {
|
|
12
|
+
const load = program.command("load").description("run a promoted Journey as a load test");
|
|
13
|
+
withEnvironmentFlags(withBrowserLaunchFlags(withEmulationFlags(load.command("run <journeyId>"))))
|
|
14
|
+
.option("--dir <path>", "journeys directory (default: the repo's .jevitate/journeys; outside a repo ~/.jevitate/journeys)")
|
|
15
|
+
.option("--param <kv>", "param as key=value (repeatable)", collectParam, {})
|
|
16
|
+
// `--authorized-origin` is mandatory, but enforced IN THE ACTION (below)
|
|
17
|
+
// via a `fail` envelope rather than commander's `.requiredOption` — which
|
|
18
|
+
// hard-exits via `process.exit`, inconsistent with this CLI's convention
|
|
19
|
+
// of emitting a JSON envelope + setting `process.exitCode` (see emitJson).
|
|
20
|
+
.option("--authorized-origin <origin>", "allowed load-test target origin (repeatable) — required, fails closed if omitted", (v, prev) => [...prev, v], [])
|
|
21
|
+
.option("--concurrency <n>", "pool size", positiveIntArg, 1)
|
|
22
|
+
.option("--iterations <n>", "iterations per actor", positiveIntArg, 1)
|
|
23
|
+
.option("--seed <n>", "master RNG seed", finiteNumberArg, 1)
|
|
24
|
+
.option("--storage-state <file>", "Playwright storageState JSON to start every actor's session authenticated (#118: required when the journey declares metadata.requiresAuth); must exist")
|
|
25
|
+
.option("--json", "emit a JSON envelope")
|
|
26
|
+
.action(async function (journeyId) {
|
|
27
|
+
const { dir, param, authorizedOrigin, concurrency, iterations, seed, storageState: storageStateFlag, json, env: envName, baseUrl, ...emulationFlags } = this.opts();
|
|
28
|
+
if (authorizedOrigin.length === 0) {
|
|
29
|
+
emitJson(program, fail("E_LOAD_RUN", "at least one --authorized-origin is required (refusing to load-test with an empty allowlist)"));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// #247: --env/--base-url choose where the load runs (unknown env / bad file → 64, nothing opened).
|
|
33
|
+
let environment;
|
|
34
|
+
try {
|
|
35
|
+
environment = environmentFromFlags({ ...(envName === undefined ? {} : { env: envName }), ...(baseUrl === undefined ? {} : { baseUrl }) }, environmentSeams(deps));
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (!isEnvironmentError(err))
|
|
39
|
+
throw err;
|
|
40
|
+
emitJson(program, fail(err.code, err.message));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const storageState = storageStateFlag ?? environment?.storageState;
|
|
44
|
+
if (storageState !== undefined && !existsSync(storageState)) {
|
|
45
|
+
emitJson(program, fail("E_LOAD_RUN_ARGS", `storage state not found: ${storageState}`));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let loadRunEmulation;
|
|
49
|
+
try {
|
|
50
|
+
loadRunEmulation = emulationFromFlags(emulationFlags);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
emitJson(program, fail("E_LOAD_RUN_ARGS", err instanceof Error ? err.message : String(err)));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const report = await withSiteGate(resolveDbPath(deps), (siteGate) => runJourneyLoadTest({
|
|
58
|
+
...(siteGate === undefined ? {} : { siteGate }),
|
|
59
|
+
dir: resolveJourneysDir(deps, dir),
|
|
60
|
+
id: journeyId,
|
|
61
|
+
params: param,
|
|
62
|
+
concurrency: Number(concurrency),
|
|
63
|
+
iterationsPerActor: Number(iterations),
|
|
64
|
+
seed: Number(seed),
|
|
65
|
+
authorizedOrigins: authorizedOrigin,
|
|
66
|
+
browserPortFactory: deps.explore?.browserPortFactory,
|
|
67
|
+
...browserOption(this.opts()),
|
|
68
|
+
...(loadRunEmulation === undefined ? {} : { emulation: loadRunEmulation }),
|
|
69
|
+
...(storageState !== undefined ? { storageState } : {}),
|
|
70
|
+
...(environment === undefined ? {} : { environment }),
|
|
71
|
+
})).then((r) => withEngine(r));
|
|
72
|
+
const envelope = ok(report);
|
|
73
|
+
if (json) {
|
|
74
|
+
emitJson(program, envelope);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
program.configureOutput().writeOut?.(`${JSON.stringify(report, null, 2)}\n`);
|
|
78
|
+
process.exitCode = 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
if (isEnvironmentError(err)) {
|
|
83
|
+
emitJson(program, fail(err.code, err.message));
|
|
84
|
+
}
|
|
85
|
+
else if (err instanceof UnknownLoadJourneyError) {
|
|
86
|
+
emitJson(program, fail("E_UNKNOWN_JOURNEY", String(err.message)));
|
|
87
|
+
}
|
|
88
|
+
else if (err instanceof JourneyRequiresAuthError) {
|
|
89
|
+
emitJson(program, fail("E_JOURNEY_REQUIRES_AUTH", String(err.message)));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
emitJson(program, fail("E_LOAD_RUN", String(err instanceof Error ? err.message : err)));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=load-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-cli.js","sourceRoot":"","sources":["../src/load-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,oBAAoB,EAA0D,MAAM,mBAAmB,CAAC;AAC3J,OAAO,EAEL,aAAa,EACb,kBAAkB,EAElB,sBAAsB,EACtB,aAAa,EAEb,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,qCAAqC;AACrC,MAAM,UAAU,oBAAoB,CAAC,OAAgB,EAAE,IAAa;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,uCAAuC,CAAC,CAAC;IAE1F,oBAAoB,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;SAC9F,MAAM,CAAC,cAAc,EAAE,kGAAkG,CAAC;SAC1H,MAAM,CAAC,cAAc,EAAE,iCAAiC,EAAE,YAAY,EAAE,EAA4B,CAAC;QACtG,yEAAyE;QACzE,0EAA0E;QAC1E,yEAAyE;QACzE,2EAA2E;SAC1E,MAAM,CACL,8BAA8B,EAC9B,kFAAkF,EAClF,CAAC,CAAC,EAAE,IAAc,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,EACnC,EAAc,CACf;SACA,MAAM,CAAC,mBAAmB,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;SAC3D,MAAM,CAAC,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,CAAC,CAAC;SACrE,MAAM,CAAC,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,CAAC,CAAC;SAC3D,MAAM,CACL,wBAAwB,EACxB,wJAAwJ,CACzJ;SACA,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAAC;SACxC,MAAM,CAAC,KAAK,WAA0B,SAAiB;QACtD,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,IAAI,EASzH,CAAC;QACzC,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,QAAQ,CACN,OAAO,EACP,IAAI,CAAC,YAAY,EAAE,8FAA8F,CAAC,CACnH,CAAC;YACF,OAAO;QACT,CAAC;QACD,mGAAmG;QACnG,IAAI,WAAmD,CAAC;QACxD,IAAI,CAAC;YACH,WAAW,GAAG,oBAAoB,CAAC,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpK,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAC;YACxC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAG,gBAAgB,IAAI,WAAW,EAAE,YAAY,CAAC;QACnE,IAAI,YAAY,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5D,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,4BAA4B,YAAY,EAAE,CAAC,CAAC,CAAC;YACvF,OAAO;QACT,CAAC;QACD,IAAI,gBAA2C,CAAC;QAChD,IAAI,CAAC;YACH,gBAAgB,GAAG,kBAAkB,CAAC,cAAc,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC7F,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,kBAAkB,CAAC;gBACtF,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;gBAC/C,GAAG,EAAE,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC;gBAClC,EAAE,EAAE,SAAS;gBACb,MAAM,EAAE,KAAK;gBACb,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;gBAChC,kBAAkB,EAAE,MAAM,CAAC,UAAU,CAAC;gBACtC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;gBAClB,iBAAiB,EAAE,gBAAgB;gBACnC,kBAAkB,EAAE,IAAI,CAAC,OAAO,EAAE,kBAAkB;gBACpD,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,EAAsB,CAAC;gBACjD,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;gBAC1E,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvD,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;aACtD,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,QAAQ,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;YAC5B,IAAI,IAAI,EAAE,CAAC;gBACT,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC9B,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,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YACjD,CAAC;iBAAM,IAAI,GAAG,YAAY,uBAAuB,EAAE,CAAC;gBAClD,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACpE,CAAC;iBAAM,IAAI,GAAG,YAAY,wBAAwB,EAAE,CAAC;gBACnD,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC1E,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC1F,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { type MissionOutcome } from "@jevitate/domain";
|
|
2
|
+
import { type TranscriptEntry } from "@jevitate/explore";
|
|
3
|
+
import { type LogSourceSpec } from "./log-sources.js";
|
|
4
|
+
import { type LogDefectMatcher, type LogIgnoreMatcher, type LogLevel } from "./log-lines.js";
|
|
5
|
+
/**
|
|
6
|
+
* Correlates tailed backend log lines to the mission step they landed during (#142): each step's
|
|
7
|
+
* "window" runs from the previous step's settle time to this step's own settle time (a mission's
|
|
8
|
+
* `TranscriptListener` fires the moment a step is recorded — already the crash-safe incremental-
|
|
9
|
+
* flush seam `MissionJournal` uses, per-step wall-clock epochs come for free from `Date.now()` at
|
|
10
|
+
* that call, with no change needed to `@jevitate/explore`'s mission loop). The LAST step's window
|
|
11
|
+
* is additionally held open for `drainMs` (`--server-log-drain-ms`) so async backend work that
|
|
12
|
+
* settles after the browser gave up is still caught, never blocking the mission itself: the
|
|
13
|
+
* runtime's own await (waiting out the drain) happens AFTER the mission function has already
|
|
14
|
+
* returned.
|
|
15
|
+
*
|
|
16
|
+
* Fail closed: every line is redacted with the run's own secret list before it is ever attached to
|
|
17
|
+
* a step, turned into a defect, or counted in the summary — a log line can contain secrets the page
|
|
18
|
+
* never showed.
|
|
19
|
+
*/
|
|
20
|
+
export interface ServerLogEvidence {
|
|
21
|
+
readonly level: LogLevel;
|
|
22
|
+
/** Redacted human message. */
|
|
23
|
+
readonly message: string;
|
|
24
|
+
/** Redacted raw line. */
|
|
25
|
+
readonly raw: string;
|
|
26
|
+
readonly source: string;
|
|
27
|
+
readonly epochMs: number;
|
|
28
|
+
/** The logger's own target/category, when known (#169). */
|
|
29
|
+
readonly target?: string;
|
|
30
|
+
}
|
|
31
|
+
export type TranscriptEntryWithLogs = TranscriptEntry & {
|
|
32
|
+
readonly serverLogs?: readonly ServerLogEvidence[];
|
|
33
|
+
};
|
|
34
|
+
export interface ServerLogSourceStatus {
|
|
35
|
+
readonly spec: string;
|
|
36
|
+
readonly opened: boolean;
|
|
37
|
+
readonly linesRead: number;
|
|
38
|
+
readonly truncated: boolean;
|
|
39
|
+
readonly error?: string;
|
|
40
|
+
/** True when this source was declared `--log-quiet-ok` (#169): zero lines from it is expected,
|
|
41
|
+
* not a sign the oracle never actually watched the backend. */
|
|
42
|
+
readonly quietOk?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface ServerLogTopMessage {
|
|
45
|
+
readonly level: LogLevel;
|
|
46
|
+
/** Normalized message class (ids/numbers/uuids/timestamps stripped). */
|
|
47
|
+
readonly message: string;
|
|
48
|
+
/** The logger's own target/category, when known (#169) — kept distinct in this summary too. */
|
|
49
|
+
readonly target?: string;
|
|
50
|
+
readonly count: number;
|
|
51
|
+
}
|
|
52
|
+
export interface ServerLogsSummary {
|
|
53
|
+
readonly sources: readonly ServerLogSourceStatus[];
|
|
54
|
+
readonly byLevel: Readonly<Record<string, number>>;
|
|
55
|
+
readonly topMessages: readonly ServerLogTopMessage[];
|
|
56
|
+
readonly attachedLines: number;
|
|
57
|
+
readonly unattributedLines: number;
|
|
58
|
+
/** Lines excluded by `--log-ignore` (#169 item 3) — known noise, never attached, never a defect
|
|
59
|
+
* candidate, not counted in `byLevel`/`topMessages`. */
|
|
60
|
+
readonly ignoredLines: number;
|
|
61
|
+
/**
|
|
62
|
+
* False when `--log-defect` was given but at least one declared source is unhealthy: it never
|
|
63
|
+
* opened/errored, OR it opened and delivered not one line while NOT declared `--log-quiet-ok`
|
|
64
|
+
* (#169) — an absence of `server-log` defects then proves nothing about the backend; it must never
|
|
65
|
+
* be read as "held"/clean (#142).
|
|
66
|
+
*/
|
|
67
|
+
readonly oracleOk: boolean;
|
|
68
|
+
/** Why `oracleOk` is false — which source(s), and whether they failed to open or were silently
|
|
69
|
+
* quiet. Unset when `oracleOk` is true. */
|
|
70
|
+
readonly oracleReason?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface ServerLogDefect {
|
|
73
|
+
readonly fingerprint: string;
|
|
74
|
+
readonly related: string[];
|
|
75
|
+
readonly kind: "server-log";
|
|
76
|
+
readonly title: string;
|
|
77
|
+
readonly route: string;
|
|
78
|
+
readonly level: LogLevel;
|
|
79
|
+
/** First occurrence's redacted message. */
|
|
80
|
+
readonly message: string;
|
|
81
|
+
readonly occurrences: number;
|
|
82
|
+
readonly repro: {
|
|
83
|
+
readonly recordingStepIndex: number;
|
|
84
|
+
};
|
|
85
|
+
/** So `verify-fix` can re-open the SAME sources and re-check the SAME matcher (#142). */
|
|
86
|
+
readonly serverLog: {
|
|
87
|
+
readonly sources: readonly string[];
|
|
88
|
+
readonly matcher: string;
|
|
89
|
+
readonly normalizedMessage: string;
|
|
90
|
+
readonly drainMs: number;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export interface ServerLogRuntimeResult {
|
|
94
|
+
readonly transcript: readonly TranscriptEntryWithLogs[];
|
|
95
|
+
readonly summary: ServerLogsSummary;
|
|
96
|
+
readonly defects: ServerLogDefect[];
|
|
97
|
+
}
|
|
98
|
+
export declare const DEFAULT_SERVER_LOG_DRAIN_MS = 3000;
|
|
99
|
+
export interface ServerLogRuntimeOptions {
|
|
100
|
+
readonly sources: readonly LogSourceSpec[];
|
|
101
|
+
/** Already-parsed `--log-defect` matchers (empty ⇒ evidence attachment only, no defects). */
|
|
102
|
+
readonly logDefect: readonly LogDefectMatcher[];
|
|
103
|
+
readonly drainMs?: number;
|
|
104
|
+
readonly secrets: readonly string[];
|
|
105
|
+
/** Raw `--log-source` specs (matched against a source's own `spec.raw`) that are allowed to
|
|
106
|
+
* deliver zero lines without making `oracleOk` false (#169's `--log-quiet-ok`). */
|
|
107
|
+
readonly quietOk?: readonly string[];
|
|
108
|
+
/** Already-parsed `--log-ignore` matchers (#169 item 3): known-noise lines excluded from
|
|
109
|
+
* correlation AND the defect oracle, counted separately (`serverLogs.ignoredLines`). */
|
|
110
|
+
readonly logIgnore?: readonly LogIgnoreMatcher[];
|
|
111
|
+
/** The journal's own listener — still called for every entry (the crash-safe flush is unchanged). */
|
|
112
|
+
readonly onTranscriptEntry?: (entry: TranscriptEntry, all: readonly TranscriptEntry[]) => void;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Opens every source and starts correlating (#142). Returns `undefined` when `sources` is empty —
|
|
116
|
+
* a complete no-op, so a run without `--log-source` pays nothing.
|
|
117
|
+
*/
|
|
118
|
+
export declare function openServerLogRuntime(opts: ServerLogRuntimeOptions): ServerLogRuntime | undefined;
|
|
119
|
+
export declare class ServerLogRuntime {
|
|
120
|
+
#private;
|
|
121
|
+
constructor(opts: ServerLogRuntimeOptions);
|
|
122
|
+
/** Wraps the journal's own `TranscriptListener`: unchanged persistence, plus this step's epoch. */
|
|
123
|
+
readonly onTranscriptEntry: (entry: TranscriptEntry, all: readonly TranscriptEntry[]) => void;
|
|
124
|
+
/** Call once the mission function has returned. Waits out the drain window, closes every source,
|
|
125
|
+
* and returns the correlated transcript/summary/defects. Idempotent (a second call is a no-op
|
|
126
|
+
* empty result) — never blocks the mission itself, only this post-processing step. */
|
|
127
|
+
finish(transcript: readonly TranscriptEntry[]): Promise<ServerLogRuntimeResult>;
|
|
128
|
+
/**
|
|
129
|
+
* Safety net for the mission-threw-before-`finish` path: closes every source immediately, with NO
|
|
130
|
+
* drain wait and no correlation. A no-op once `finish` already ran. Never throws.
|
|
131
|
+
*/
|
|
132
|
+
abort(): Promise<void>;
|
|
133
|
+
}
|
|
134
|
+
/** Parses `--log-defect` values, failing closed on the first bad one. */
|
|
135
|
+
export declare function parseLogDefectSpecs(raw: readonly string[]): LogDefectMatcher[];
|
|
136
|
+
/** Parses `--log-ignore` values, failing closed on the first bad one (#169 item 3). */
|
|
137
|
+
export declare function parseLogIgnoreSpecs(raw: readonly string[]): LogIgnoreMatcher[];
|
|
138
|
+
/**
|
|
139
|
+
* Folds a server-log correlation result into an already-computed `MissionOutcome` (#142, follow-up
|
|
140
|
+
* on the exit-code requirement): a found `server-log` defect is at least `defects-found` — via
|
|
141
|
+
* `worstOutcome`, so it never DOWNGRADES a worse outcome (hang/crashed/inconclusive already proves
|
|
142
|
+
* more, or the same, than a defect). An unreadable `--log-defect` oracle (`oracleOk: false`) turns
|
|
143
|
+
* an otherwise-`clean` run `inconclusive` — its absence of defects proves nothing when the source
|
|
144
|
+
* that would have caught them was never demonstrably read. `undefined` (no `--log-source`) is a
|
|
145
|
+
* complete no-op.
|
|
146
|
+
*/
|
|
147
|
+
export declare function applyServerLogOutcome(outcome: MissionOutcome, run: ServerLogRuntimeResult | undefined): MissionOutcome;
|