@jevitate/cli 0.2.0 → 0.4.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/dist/ai-cli.d.ts +31 -11
- package/dist/ai-cli.js +100 -67
- package/dist/ai-cli.js.map +1 -1
- package/dist/author-journey-cli.js +3 -1
- package/dist/author-journey-cli.js.map +1 -1
- package/dist/bin.js +48715 -40027
- package/dist/browser-run-options.d.ts +32 -1
- package/dist/browser-run-options.js +69 -0
- package/dist/browser-run-options.js.map +1 -1
- package/dist/build-info.generated.js +2 -2
- package/dist/campaign-api.d.ts +153 -0
- package/dist/campaign-api.js +447 -0
- package/dist/campaign-api.js.map +1 -0
- package/dist/campaign-cli.d.ts +8 -0
- package/dist/campaign-cli.js +109 -0
- package/dist/campaign-cli.js.map +1 -0
- package/dist/check-api.js +3 -2
- package/dist/check-api.js.map +1 -1
- package/dist/check-budget.js +2 -1
- package/dist/check-budget.js.map +1 -1
- package/dist/check-execute.d.ts +4 -0
- package/dist/check-execute.js +46 -10
- package/dist/check-execute.js.map +1 -1
- package/dist/check-plan.d.ts +5 -0
- package/dist/check-plan.js +77 -4
- package/dist/check-plan.js.map +1 -1
- package/dist/check-suite.d.ts +14 -1
- package/dist/check-suite.js +26 -1
- package/dist/check-suite.js.map +1 -1
- package/dist/cli-output.d.ts +4 -0
- package/dist/cli-output.js +52 -5
- package/dist/cli-output.js.map +1 -1
- package/dist/cli-shared.d.ts +13 -3
- package/dist/cli-shared.js +52 -7
- package/dist/cli-shared.js.map +1 -1
- package/dist/defect-evidence.d.ts +3 -2
- package/dist/defect-evidence.js +12 -8
- package/dist/defect-evidence.js.map +1 -1
- package/dist/demo-aspect-api.js +2 -1
- package/dist/demo-aspect-api.js.map +1 -1
- package/dist/demo-aspect-cli.js +3 -1
- package/dist/demo-aspect-cli.js.map +1 -1
- package/dist/demo-capture.d.ts +37 -3
- package/dist/demo-capture.js +119 -20
- package/dist/demo-capture.js.map +1 -1
- package/dist/explore-adversarial.d.ts +11 -4
- package/dist/explore-adversarial.js +22 -13
- package/dist/explore-adversarial.js.map +1 -1
- package/dist/explore-cli.js +282 -31
- package/dist/explore-cli.js.map +1 -1
- package/dist/explore-coverage.d.ts +17 -2
- package/dist/explore-coverage.js +20 -14
- package/dist/explore-coverage.js.map +1 -1
- package/dist/explore-feature.d.ts +0 -2
- package/dist/explore-feature.js +7 -9
- package/dist/explore-feature.js.map +1 -1
- package/dist/explore-goal.d.ts +25 -7
- package/dist/explore-goal.js +62 -19
- package/dist/explore-goal.js.map +1 -1
- package/dist/explore-shared.d.ts +53 -3
- package/dist/explore-shared.js +48 -1
- package/dist/explore-shared.js.map +1 -1
- package/dist/fixture-auth.d.ts +13 -2
- package/dist/fixture-auth.js +19 -6
- package/dist/fixture-auth.js.map +1 -1
- package/dist/fixture-cli.d.ts +29 -0
- package/dist/fixture-cli.js +121 -7
- package/dist/fixture-cli.js.map +1 -1
- package/dist/github-issue-filer.js +2 -1
- package/dist/github-issue-filer.js.map +1 -1
- package/dist/host-health-run.d.ts +2 -1
- package/dist/host-health-run.js +8 -2
- package/dist/host-health-run.js.map +1 -1
- package/dist/init-cli.js +34 -5
- package/dist/init-cli.js.map +1 -1
- package/dist/init-keys.d.ts +11 -0
- package/dist/init-keys.js +5 -2
- package/dist/init-keys.js.map +1 -1
- package/dist/journey-annotate-api.js +17 -4
- package/dist/journey-annotate-api.js.map +1 -1
- package/dist/journey-annotate-cli.js +3 -1
- package/dist/journey-annotate-cli.js.map +1 -1
- package/dist/journey-api.d.ts +26 -1
- package/dist/journey-api.js +51 -25
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.d.ts +1 -1
- package/dist/journey-cli.js +44 -3
- package/dist/journey-cli.js.map +1 -1
- package/dist/journey-demo-api.d.ts +2 -0
- package/dist/journey-demo-api.js +23 -10
- package/dist/journey-demo-api.js.map +1 -1
- package/dist/journey-demo-cli.js +5 -2
- package/dist/journey-demo-cli.js.map +1 -1
- package/dist/journey-prefix.d.ts +194 -0
- package/dist/journey-prefix.js +279 -0
- package/dist/journey-prefix.js.map +1 -0
- package/dist/key-report.d.ts +49 -0
- package/dist/key-report.js +101 -0
- package/dist/key-report.js.map +1 -0
- package/dist/kill-signal.js +0 -1
- package/dist/kill-signal.js.map +1 -1
- package/dist/ledger-api.js +3 -1
- package/dist/ledger-api.js.map +1 -1
- package/dist/log-correlation.d.ts +63 -1
- package/dist/log-correlation.js +125 -16
- package/dist/log-correlation.js.map +1 -1
- package/dist/log-sources.js +6 -5
- package/dist/log-sources.js.map +1 -1
- package/dist/log-trace.d.ts +80 -0
- package/dist/log-trace.js +210 -0
- package/dist/log-trace.js.map +1 -0
- package/dist/logs-cli.js +60 -1
- package/dist/logs-cli.js.map +1 -1
- package/dist/logs-retention.js +2 -1
- package/dist/logs-retention.js.map +1 -1
- package/dist/masked-input.d.ts +22 -0
- package/dist/masked-input.js +99 -0
- package/dist/masked-input.js.map +1 -0
- package/dist/mcp-api.d.ts +3 -1
- package/dist/mcp-api.js +49 -7
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-args.d.ts +12 -0
- package/dist/mcp-args.js +33 -0
- package/dist/mcp-args.js.map +1 -1
- package/dist/mcp-cli-tools.d.ts +6 -1
- package/dist/mcp-cli-tools.js +103 -16
- package/dist/mcp-cli-tools.js.map +1 -1
- package/dist/mission-api.js +2 -1
- package/dist/mission-api.js.map +1 -1
- package/dist/mission-cli.js +3 -1
- package/dist/mission-cli.js.map +1 -1
- package/dist/mission-fixtures.d.ts +10 -1
- package/dist/mission-fixtures.js +49 -15
- package/dist/mission-fixtures.js.map +1 -1
- package/dist/mission-queue-runner.d.ts +2 -0
- package/dist/mission-queue-runner.js +18 -5
- package/dist/mission-queue-runner.js.map +1 -1
- package/dist/multi-run-cli.js +7 -1
- package/dist/multi-run-cli.js.map +1 -1
- package/dist/openrouter-call.js +3 -2
- package/dist/openrouter-call.js.map +1 -1
- package/dist/program.js +4 -0
- package/dist/program.js.map +1 -1
- package/dist/project-dir.js +3 -2
- package/dist/project-dir.js.map +1 -1
- package/dist/record-api.d.ts +3 -1
- package/dist/record-api.js +5 -2
- package/dist/record-api.js.map +1 -1
- package/dist/record-cli.js +14 -2
- package/dist/record-cli.js.map +1 -1
- package/dist/regression-api.d.ts +6 -0
- package/dist/regression-api.js +4 -2
- package/dist/regression-api.js.map +1 -1
- package/dist/regression-cli.js +56 -4
- package/dist/regression-cli.js.map +1 -1
- package/dist/report-api.js +2 -1
- package/dist/report-api.js.map +1 -1
- package/dist/resource-preflight.d.ts +87 -0
- package/dist/resource-preflight.js +160 -0
- package/dist/resource-preflight.js.map +1 -0
- package/dist/result-schema.d.ts +1 -1
- package/dist/result-schema.js +1 -1
- package/dist/run-key-preflight.d.ts +42 -0
- package/dist/run-key-preflight.js +82 -0
- package/dist/run-key-preflight.js.map +1 -0
- package/dist/run-screenshots.js +11 -5
- package/dist/run-screenshots.js.map +1 -1
- package/dist/runtime-env.js +3 -2
- package/dist/runtime-env.js.map +1 -1
- package/dist/server-log-verify.d.ts +2 -0
- package/dist/server-log-verify.js +8 -3
- package/dist/server-log-verify.js.map +1 -1
- package/dist/signal-triage.d.ts +147 -0
- package/dist/signal-triage.js +281 -0
- package/dist/signal-triage.js.map +1 -0
- package/dist/site-gate-cli.js +2 -1
- package/dist/site-gate-cli.js.map +1 -1
- package/dist/source-api.js +2 -1
- package/dist/source-api.js.map +1 -1
- package/dist/suite-explore-options.d.ts +36 -0
- package/dist/suite-explore-options.js +23 -0
- package/dist/suite-explore-options.js.map +1 -1
- package/dist/target-config.d.ts +12 -0
- package/dist/target-config.js +15 -0
- package/dist/target-config.js.map +1 -1
- package/dist/type-fixture-file.d.ts +9 -0
- package/dist/type-fixture-file.js +48 -0
- package/dist/type-fixture-file.js.map +1 -0
- package/dist/ui-api.js +4 -3
- package/dist/ui-api.js.map +1 -1
- package/dist/usability-capture.js +4 -3
- package/dist/usability-capture.js.map +1 -1
- package/dist/usage-config.d.ts +1 -1
- package/dist/usage-config.js +1 -1
- package/dist/ux-claim-probe.d.ts +45 -0
- package/dist/ux-claim-probe.js +386 -0
- package/dist/ux-claim-probe.js.map +1 -0
- package/dist/ux-cli.js +8 -1
- package/dist/ux-cli.js.map +1 -1
- package/dist/ux-product.d.ts +14 -0
- package/dist/ux-product.js +39 -0
- package/dist/ux-product.js.map +1 -0
- package/dist/ux-review.d.ts +4 -0
- package/dist/ux-review.js +27 -7
- package/dist/ux-review.js.map +1 -1
- package/dist/ux-usability.d.ts +34 -9
- package/dist/ux-usability.js +102 -16
- package/dist/ux-usability.js.map +1 -1
- package/dist/verify-fix-api.d.ts +21 -0
- package/dist/verify-fix-api.js +85 -33
- package/dist/verify-fix-api.js.map +1 -1
- package/dist/verify-fix-cli.js +7 -2
- package/dist/verify-fix-cli.js.map +1 -1
- package/package.json +11 -11
- package/skills/jevitate-explore/SKILL.md +13 -0
- package/skills/jevitate-getting-started/SKILL.md +2 -1
- package/skills/jevitate-test-campaign/SKILL.md +206 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
5
|
+
import { FsJourneyStore, JourneyRegistry, JourneyStepError, deriveParamSchema, journeyBranchPoint, journeyPrefix, resolveJourneyStep, validateParams, CAMPAIGN_LIMITS, CampaignSpecSchema, splitBudget, sweepStops, } from "@jevitate/journey";
|
|
6
|
+
import { assertSafeName, combineOutcomes, MISSION_OUTCOMES, clock } from "@jevitate/domain";
|
|
7
|
+
import { applyJourneyEnvironment, environmentFromFlags, isEnvironmentError } from "./environments.js";
|
|
8
|
+
import { prefixParams } from "./journey-api.js";
|
|
9
|
+
import { buildMissionFixtures } from "./fixture-cli.js";
|
|
10
|
+
import { FixtureSetupError, FixtureSpecError } from "./mission-fixtures.js";
|
|
11
|
+
import { lastEnvelope } from "./multi-run-cli.js";
|
|
12
|
+
import { buildReport, loadRunFile } from "./report-api.js";
|
|
13
|
+
import { exitCodeForOutcome } from "./exit-codes.js";
|
|
14
|
+
import { artifactStamp } from "./mission-journal.js";
|
|
15
|
+
import { logsDirFor } from "./project-dir.js";
|
|
16
|
+
/**
|
|
17
|
+
* #293 — `jevitate campaign run <spec.json>`: many journey-anchored missions, run in order, read as
|
|
18
|
+
* ONE deduped report.
|
|
19
|
+
*
|
|
20
|
+
* A campaign spec lists jobs: a promoted Journey, the anchors (names or step numbers) to branch off,
|
|
21
|
+
* the strategies to run from each, and their budgets. The run is:
|
|
22
|
+
*
|
|
23
|
+
* 1. discovery — each job's whole Journey is replayed once (`journey run`, fail-closed): a stale
|
|
24
|
+
* Journey is reported and its missions are skipped (`journey-stale`), never run from a URL;
|
|
25
|
+
* 2. anchored missions, in spec order (job → anchor → strategy): each is `explore --from-journey
|
|
26
|
+
* <id> --at-step <anchor> --strategy <s>` (its own fresh browser context), with the campaign's
|
|
27
|
+
* state restore around it — the `--fixtures` setup/restore semantics (and operator hooks when
|
|
28
|
+
* `--allow-shell-hooks` is given) — so one mission's side effects never leak into the next;
|
|
29
|
+
* 3. one report — every mission's persisted result consolidated by `@jevitate/findings` (the same
|
|
30
|
+
* dedupe as `jevitate report`), each defect listing the Journey steps it branched from.
|
|
31
|
+
*
|
|
32
|
+
* Bounded: at most 50 jobs and `maxRuns` missions (default 50, at most 200), each with an action
|
|
33
|
+
* budget (default 40). An invalid spec is refused with EVERY problem listed (E_CAMPAIGN_SPEC, exit
|
|
34
|
+
* 64) before any browser opens. The campaign's outcome is the worst of its missions' (a broken or
|
|
35
|
+
* stale mission dominates, as `combineOutcomes` rules) — the report keeps every finding either way.
|
|
36
|
+
*/
|
|
37
|
+
export { CAMPAIGN_LIMITS, CampaignSpecSchema } from "@jevitate/journey";
|
|
38
|
+
/** The spec cannot be run as given — every problem listed (exit 64, nothing ran). */
|
|
39
|
+
export class CampaignSpecError extends Error {
|
|
40
|
+
problems;
|
|
41
|
+
code = "E_CAMPAIGN_SPEC";
|
|
42
|
+
constructor(problems) {
|
|
43
|
+
super(`invalid campaign spec (${problems.length} problem${problems.length === 1 ? "" : "s"}):\n${problems.map((p) => ` - ${p}`).join("\n")}`);
|
|
44
|
+
this.problems = problems;
|
|
45
|
+
this.name = "CampaignSpecError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const at = (path) => (path.length === 0 ? "spec" : path.map((p) => (typeof p === "number" ? `[${p}]` : `.${String(p)}`)).join("").replace(/^\./, ""));
|
|
49
|
+
/**
|
|
50
|
+
* Reads and validates a campaign spec against the Journey store — structure, then every job's
|
|
51
|
+
* Journey (exists, promoted), anchors, params, session, strategies' inputs, the fixtures and the
|
|
52
|
+
* run cap — and returns the plan. Throws `CampaignSpecError` listing EVERY problem found.
|
|
53
|
+
*/
|
|
54
|
+
export async function validateCampaign(specPath, opts) {
|
|
55
|
+
let raw;
|
|
56
|
+
try {
|
|
57
|
+
raw = JSON.parse(readFileSync(specPath, "utf8"));
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
throw new CampaignSpecError([`cannot read ${specPath}: ${e instanceof SyntaxError ? "not valid JSON" : e instanceof Error ? e.message : String(e)}`]);
|
|
61
|
+
}
|
|
62
|
+
return validateCampaignSpec(raw, resolve(specPath), opts);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validates a campaign spec OBJECT (`specPath` names where it came from; its relative paths resolve
|
|
66
|
+
* against that file's directory) — what `explore --at-step all|anchors` builds for its sweep.
|
|
67
|
+
*/
|
|
68
|
+
export async function validateCampaignSpec(raw, specPath, opts) {
|
|
69
|
+
const parsed = CampaignSpecSchema.safeParse(raw);
|
|
70
|
+
if (!parsed.success)
|
|
71
|
+
throw new CampaignSpecError(parsed.error.issues.map((i) => `${at(i.path)}: ${i.message}`));
|
|
72
|
+
const spec = parsed.data;
|
|
73
|
+
const base = dirname(resolve(specPath));
|
|
74
|
+
// A spec path is relative to the spec file; `~/` is the home directory (sessions live in ~/.jevitate).
|
|
75
|
+
const abs = (p) => (p.startsWith("~/") ? join(homedir(), p.slice(2)) : isAbsolute(p) ? p : resolve(base, p));
|
|
76
|
+
const problems = [];
|
|
77
|
+
let environment;
|
|
78
|
+
try {
|
|
79
|
+
environment = environmentFromFlags({ ...(spec.env === undefined ? {} : { env: spec.env }), ...(spec.baseUrl === undefined ? {} : { baseUrl: spec.baseUrl }) }, opts.environmentSeams ?? {});
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
if (!isEnvironmentError(err))
|
|
83
|
+
throw err;
|
|
84
|
+
problems.push(`env: ${err.message}`);
|
|
85
|
+
}
|
|
86
|
+
const defaultSession = spec.storageState === undefined ? environment?.storageState : abs(spec.storageState);
|
|
87
|
+
if (spec.storageState !== undefined && !existsSync(abs(spec.storageState)))
|
|
88
|
+
problems.push(`storageState: not found: ${abs(spec.storageState)}`);
|
|
89
|
+
if (spec.fixtures !== undefined && !existsSync(abs(spec.fixtures)))
|
|
90
|
+
problems.push(`fixtures: not found: ${abs(spec.fixtures)}`);
|
|
91
|
+
if ((spec.before !== undefined || spec.after !== undefined) && opts.allowShellHooks !== true) {
|
|
92
|
+
problems.push("before/after: operator shell hooks run only with --allow-shell-hooks");
|
|
93
|
+
}
|
|
94
|
+
const registry = new JourneyRegistry(new FsJourneyStore(opts.journeysDir));
|
|
95
|
+
const seen = new Set();
|
|
96
|
+
const jobs = [];
|
|
97
|
+
let totalRuns = 0;
|
|
98
|
+
for (const [i, job] of spec.jobs.entries()) {
|
|
99
|
+
const where = `jobs[${i}]${job.id === "" ? "" : ` (${job.id})`}`;
|
|
100
|
+
try {
|
|
101
|
+
assertSafeName(job.id, "job id");
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
problems.push(`${where}.id: ${err instanceof Error ? err.message : String(err)}`);
|
|
105
|
+
}
|
|
106
|
+
if (seen.has(job.id))
|
|
107
|
+
problems.push(`${where}.id: duplicate job id ${JSON.stringify(job.id)}`);
|
|
108
|
+
seen.add(job.id);
|
|
109
|
+
const needsGoal = job.strategies.filter((s) => s === "goal" || s === "usability");
|
|
110
|
+
if (needsGoal.length > 0 && job.goal === undefined)
|
|
111
|
+
problems.push(`${where}.goal: required by strategy ${needsGoal.join(", ")}`);
|
|
112
|
+
if (job.strategies.includes("usability") && job.appClass === undefined)
|
|
113
|
+
problems.push(`${where}.appClass: required by strategy usability`);
|
|
114
|
+
if (job.success !== undefined && needsGoal.length !== job.strategies.length) {
|
|
115
|
+
problems.push(`${where}.success: checks apply only to goal and usability missions — give them a job of their own`);
|
|
116
|
+
}
|
|
117
|
+
if (new Set(job.strategies).size !== job.strategies.length)
|
|
118
|
+
problems.push(`${where}.strategies: duplicate strategy`);
|
|
119
|
+
const session = job.storageState === undefined ? defaultSession : abs(job.storageState);
|
|
120
|
+
if (job.storageState !== undefined && !existsSync(abs(job.storageState)))
|
|
121
|
+
problems.push(`${where}.storageState: not found: ${abs(job.storageState)}`);
|
|
122
|
+
let stored = null;
|
|
123
|
+
try {
|
|
124
|
+
stored = await registry.get(job.journey);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
problems.push(`${where}.journey: ${err instanceof Error ? err.message.split("\n")[0] : String(err)}`);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (stored === null) {
|
|
131
|
+
problems.push(`${where}.journey: unknown journey '${job.journey}'`);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (!stored.metadata.promoted)
|
|
135
|
+
problems.push(`${where}.journey: journey '${job.journey}' is not promoted (a person promotes it: jevitate journey promote ${job.journey})`);
|
|
136
|
+
let full = stored;
|
|
137
|
+
try {
|
|
138
|
+
full = applyJourneyEnvironment(stored, environment);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
problems.push(`${where}.journey: ${err instanceof Error ? err.message : String(err)}`);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (full.metadata.requiresAuth === true && session === undefined)
|
|
145
|
+
problems.push(`${where}: journey '${job.journey}' requires auth — give storageState`);
|
|
146
|
+
// #293: a sweep — every step ("all") or every declared anchor ("anchors") — or the listed stops.
|
|
147
|
+
let refs = [];
|
|
148
|
+
const sweep = typeof job.anchors === "string" ? job.anchors : undefined;
|
|
149
|
+
try {
|
|
150
|
+
refs = sweep !== undefined ? sweepStops(full, sweep) : job.anchors ?? (full.metadata.anchors ?? []).map((a) => a.name);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (!(err instanceof JourneyStepError))
|
|
154
|
+
throw err;
|
|
155
|
+
problems.push(`${where}.anchors: ${err.message}`);
|
|
156
|
+
}
|
|
157
|
+
if (refs.length === 0 && sweep === undefined)
|
|
158
|
+
problems.push(`${where}.anchors: journey '${job.journey}' declares no anchors — list anchor names or step numbers`);
|
|
159
|
+
const anchors = [];
|
|
160
|
+
for (const [k, ref] of refs.entries()) {
|
|
161
|
+
try {
|
|
162
|
+
const resolved = resolveJourneyStep(full, String(ref));
|
|
163
|
+
anchors.push({ atStep: resolved.anchor?.name ?? String(resolved.step), branch: journeyBranchPoint(full, resolved) });
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
if (!(err instanceof JourneyStepError))
|
|
167
|
+
throw err;
|
|
168
|
+
problems.push(`${where}.anchors[${k}]: ${err.message}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (new Set(anchors.map((a) => a.branch.step)).size !== anchors.length)
|
|
172
|
+
problems.push(`${where}.anchors: two anchors name the same step`);
|
|
173
|
+
const deepest = Math.max(0, ...anchors.map((a) => a.branch.step));
|
|
174
|
+
if (deepest > 0) {
|
|
175
|
+
try {
|
|
176
|
+
const prefix = journeyPrefix(full, deepest);
|
|
177
|
+
validateParams(deriveParamSchema(prefix.recording), prefixParams(full, prefix, job.params ?? {}));
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
problems.push(`${where}.params: ${err instanceof Error ? err.message : String(err)}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
let fixtures;
|
|
184
|
+
if (spec.fixtures !== undefined || spec.before !== undefined || spec.after !== undefined) {
|
|
185
|
+
try {
|
|
186
|
+
fixtures = buildMissionFixtures({
|
|
187
|
+
...(spec.fixtures === undefined ? {} : { fixtures: abs(spec.fixtures) }),
|
|
188
|
+
...(spec.before === undefined ? {} : { before: spec.before }),
|
|
189
|
+
...(spec.after === undefined ? {} : { after: spec.after }),
|
|
190
|
+
allowShellHooks: opts.allowShellHooks === true,
|
|
191
|
+
...(opts.hookTimeoutMs === undefined ? {} : { hookTimeoutMs: String(opts.hookTimeoutMs) }),
|
|
192
|
+
}, {
|
|
193
|
+
allowlist: environment === undefined ? [new URL(full.recording.site).origin] : environment.allowedOrigins,
|
|
194
|
+
baseUrl: full.recording.site,
|
|
195
|
+
...(session === undefined ? {} : { storageState: session }),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
if (!(err instanceof FixtureSpecError) && !(err instanceof TypeError))
|
|
200
|
+
throw err;
|
|
201
|
+
// Reported once for the campaign, not per job.
|
|
202
|
+
const message = `fixtures: ${err.message}`;
|
|
203
|
+
if (!problems.includes(message))
|
|
204
|
+
problems.push(message);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
totalRuns += anchors.length * job.strategies.length;
|
|
208
|
+
jobs.push({
|
|
209
|
+
id: job.id,
|
|
210
|
+
journey: job.journey,
|
|
211
|
+
params: job.params ?? {},
|
|
212
|
+
...(session === undefined ? {} : { storageState: session }),
|
|
213
|
+
anchors,
|
|
214
|
+
strategies: job.strategies,
|
|
215
|
+
...(job.goal === undefined ? {} : { goal: job.goal }),
|
|
216
|
+
...(job.appClass === undefined ? {} : { appClass: job.appClass }),
|
|
217
|
+
success: job.success ?? [],
|
|
218
|
+
// #293: a sweep's budgets are its TOTAL, split evenly over its missions (stop points × strategies).
|
|
219
|
+
...budgetsOf(job.maxActions ?? spec.maxActions, job.maxDecisions ?? spec.maxDecisions, sweep === undefined ? 1 : anchors.length * job.strategies.length),
|
|
220
|
+
...(sweep === undefined ? {} : { sweep }),
|
|
221
|
+
...(fixtures === undefined ? {} : { fixtures }),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const cap = spec.maxRuns ?? CAMPAIGN_LIMITS.defaultMaxRuns;
|
|
225
|
+
if (totalRuns > cap)
|
|
226
|
+
problems.push(`jobs: ${totalRuns} anchored missions exceed maxRuns ${cap} (raise maxRuns, at most ${CAMPAIGN_LIMITS.maxRuns}, or split the campaign)`);
|
|
227
|
+
if (problems.length > 0)
|
|
228
|
+
throw new CampaignSpecError(problems);
|
|
229
|
+
return {
|
|
230
|
+
...(spec.name === undefined ? {} : { name: spec.name }),
|
|
231
|
+
specPath: resolve(specPath),
|
|
232
|
+
...(spec.env === undefined ? {} : { env: spec.env }),
|
|
233
|
+
...(spec.baseUrl === undefined ? {} : { baseUrl: spec.baseUrl }),
|
|
234
|
+
discovery: spec.discovery ?? true,
|
|
235
|
+
totalRuns,
|
|
236
|
+
jobs,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
async function runChild(newProgram, argv) {
|
|
240
|
+
const lines = [];
|
|
241
|
+
const child = newProgram();
|
|
242
|
+
child.exitOverride();
|
|
243
|
+
child.configureOutput({ writeOut: (s) => lines.push(s), writeErr: () => undefined });
|
|
244
|
+
const saved = process.exitCode;
|
|
245
|
+
try {
|
|
246
|
+
await child.parseAsync([...argv], { from: "user" });
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
return { ok: false, error: { code: "E_CAMPAIGN_RUN", message: err instanceof Error ? err.message : String(err) } };
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
process.exitCode = saved;
|
|
253
|
+
}
|
|
254
|
+
const env = lastEnvelope(lines);
|
|
255
|
+
if (!env.ok)
|
|
256
|
+
return { ok: false, error: env.error ?? { code: "E_CAMPAIGN_RUN", message: "the run failed" } };
|
|
257
|
+
return { ok: true, data: (env.data ?? {}) };
|
|
258
|
+
}
|
|
259
|
+
const isOutcome = (v) => typeof v === "string" && MISSION_OUTCOMES.includes(v);
|
|
260
|
+
/**
|
|
261
|
+
* Per-mission budgets: as given for listed stops; for a sweep (`missions` > 1 stop × strategy) the
|
|
262
|
+
* given value is the sweep's TOTAL, split evenly (each mission at least 1 action). Without a value,
|
|
263
|
+
* every mission gets the default 40 actions.
|
|
264
|
+
*/
|
|
265
|
+
function budgetsOf(maxActions, maxDecisions, missions) {
|
|
266
|
+
return {
|
|
267
|
+
maxActions: maxActions === undefined ? CAMPAIGN_LIMITS.defaultMaxActions : splitBudget(maxActions, missions),
|
|
268
|
+
...(maxDecisions === undefined ? {} : { maxDecisions: splitBudget(maxDecisions, missions) }),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/** The flags a job's discovery replay and its missions share: params, environment, session. */
|
|
272
|
+
function commonArgs(plan, job) {
|
|
273
|
+
return [
|
|
274
|
+
...Object.entries(job.params).flatMap(([k, v]) => ["--param", `${k}=${v}`]),
|
|
275
|
+
...(plan.env === undefined ? [] : ["--env", plan.env]),
|
|
276
|
+
...(plan.baseUrl === undefined ? [] : ["--base-url", plan.baseUrl]),
|
|
277
|
+
...(job.storageState === undefined ? [] : ["--storage-state", job.storageState]),
|
|
278
|
+
];
|
|
279
|
+
}
|
|
280
|
+
/** Runs a validated campaign: discovery, then every anchored mission in order with state restore, then one report. */
|
|
281
|
+
export async function runCampaign(plan, opts) {
|
|
282
|
+
const now = opts.nowIso ?? (() => clock.nowIso());
|
|
283
|
+
const startedAt = now();
|
|
284
|
+
const outDir = opts.outDir ?? join(logsDirFor(startedAt), `campaign-${artifactStamp(startedAt)}`);
|
|
285
|
+
await mkdir(outDir, { recursive: true });
|
|
286
|
+
const ai = opts.real === true ? ["--real"] : opts.fakeAi === true ? ["--fake-ai"] : [];
|
|
287
|
+
const discovery = [];
|
|
288
|
+
const missions = [];
|
|
289
|
+
/** Runs `body` between the job's fixture setup and restore (a failed setup still restores). */
|
|
290
|
+
const restored = async (job, body, onSetupFailed) => {
|
|
291
|
+
const fx = job.fixtures;
|
|
292
|
+
if (fx === undefined)
|
|
293
|
+
return body();
|
|
294
|
+
try {
|
|
295
|
+
await fx.setup();
|
|
296
|
+
}
|
|
297
|
+
catch (err) {
|
|
298
|
+
await fx.restore();
|
|
299
|
+
if (err instanceof FixtureSetupError)
|
|
300
|
+
return onSetupFailed(err.message);
|
|
301
|
+
throw err;
|
|
302
|
+
}
|
|
303
|
+
try {
|
|
304
|
+
return await body();
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
await fx.restore();
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
for (const job of plan.jobs) {
|
|
311
|
+
const shared = commonArgs(plan, job);
|
|
312
|
+
let stale;
|
|
313
|
+
if (plan.discovery) {
|
|
314
|
+
const d = await restored(job, async () => {
|
|
315
|
+
const r = await runChild(opts.newProgram, ["journey", "run", job.journey, "--dir", opts.journeysDir, ...shared, "--json"]);
|
|
316
|
+
if (!r.ok)
|
|
317
|
+
return { job: job.id, journeyId: job.journey, outcome: "error", reason: `${r.error?.code}: ${r.error?.message}` };
|
|
318
|
+
const outcome = r.data?.outcome;
|
|
319
|
+
if (outcome === "ok")
|
|
320
|
+
return { job: job.id, journeyId: job.journey, outcome: "ok" };
|
|
321
|
+
return { job: job.id, journeyId: job.journey, outcome: "stale", reason: typeof r.data?.reason === "string" ? r.data.reason : `the replay ended ${String(outcome)}` };
|
|
322
|
+
}, (message) => ({ job: job.id, journeyId: job.journey, outcome: "error", reason: `fixture setup failed: ${message}` }));
|
|
323
|
+
discovery.push(d);
|
|
324
|
+
if (d.outcome !== "ok")
|
|
325
|
+
stale = d.reason ?? d.outcome;
|
|
326
|
+
}
|
|
327
|
+
for (const anchor of job.anchors) {
|
|
328
|
+
for (const strategy of job.strategies) {
|
|
329
|
+
if (stale !== undefined) {
|
|
330
|
+
missions.push({
|
|
331
|
+
job: job.id,
|
|
332
|
+
strategy,
|
|
333
|
+
branch: anchor.branch,
|
|
334
|
+
status: "skipped",
|
|
335
|
+
missionOutcome: "inconclusive",
|
|
336
|
+
exitCode: exitCodeForOutcome("inconclusive"),
|
|
337
|
+
failure: { kind: "journey-stale", message: `discovery: journey '${job.journey}' did not replay (${stale})` },
|
|
338
|
+
});
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
const runDir = join(outDir, job.id, `${anchor.atStep}-${strategy}`);
|
|
342
|
+
const argv = [
|
|
343
|
+
"explore",
|
|
344
|
+
"--from-journey", job.journey,
|
|
345
|
+
"--at-step", anchor.atStep,
|
|
346
|
+
"--strategy", strategy,
|
|
347
|
+
"--journeys-dir", opts.journeysDir,
|
|
348
|
+
...shared,
|
|
349
|
+
"--max-actions", String(job.maxActions),
|
|
350
|
+
...(job.maxDecisions === undefined ? [] : ["--max-decisions", String(job.maxDecisions)]),
|
|
351
|
+
...(strategy === "goal" || strategy === "usability" ? [...(job.goal === undefined ? [] : ["--goal", job.goal]), ...job.success.flatMap((c) => ["--success", c])] : []),
|
|
352
|
+
...(strategy === "usability" && job.appClass !== undefined ? ["--app-class", job.appClass] : []),
|
|
353
|
+
...ai,
|
|
354
|
+
...(opts.missionArgs ?? []),
|
|
355
|
+
"--out", runDir,
|
|
356
|
+
"--json",
|
|
357
|
+
];
|
|
358
|
+
const m = await restored(job, async () => {
|
|
359
|
+
const r = await runChild(opts.newProgram, argv);
|
|
360
|
+
if (!r.ok) {
|
|
361
|
+
return {
|
|
362
|
+
job: job.id,
|
|
363
|
+
strategy,
|
|
364
|
+
branch: anchor.branch,
|
|
365
|
+
status: "error",
|
|
366
|
+
missionOutcome: "inconclusive",
|
|
367
|
+
exitCode: exitCodeForOutcome("inconclusive"),
|
|
368
|
+
failure: { kind: "mission-error", message: `${r.error?.code}: ${r.error?.message}` },
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const data = r.data ?? {};
|
|
372
|
+
const outcome = isOutcome(data.missionOutcome) ? data.missionOutcome : "inconclusive";
|
|
373
|
+
const failure = data.failure;
|
|
374
|
+
return {
|
|
375
|
+
job: job.id,
|
|
376
|
+
strategy,
|
|
377
|
+
branch: anchor.branch,
|
|
378
|
+
status: "ran",
|
|
379
|
+
missionOutcome: outcome,
|
|
380
|
+
exitCode: typeof data.exitCode === "number" ? data.exitCode : exitCodeForOutcome(outcome),
|
|
381
|
+
...(typeof data.resultPath === "string" ? { resultPath: data.resultPath } : {}),
|
|
382
|
+
...(failure !== undefined && typeof failure.kind === "string" ? { failure: { kind: failure.kind, message: String(failure.message ?? "") } } : {}),
|
|
383
|
+
};
|
|
384
|
+
}, (message) => ({
|
|
385
|
+
job: job.id,
|
|
386
|
+
strategy,
|
|
387
|
+
branch: anchor.branch,
|
|
388
|
+
status: "error",
|
|
389
|
+
missionOutcome: "inconclusive",
|
|
390
|
+
exitCode: exitCodeForOutcome("inconclusive"),
|
|
391
|
+
failure: { kind: "configuration", message: `fixture setup failed: ${message}` },
|
|
392
|
+
}));
|
|
393
|
+
missions.push(job.fixtures === undefined ? m : { ...m, restored: true });
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// One deduped report over every mission that persisted a result.
|
|
398
|
+
const runs = missions.flatMap((m) => {
|
|
399
|
+
if (m.resultPath === undefined)
|
|
400
|
+
return [];
|
|
401
|
+
const r = loadRunFile(m.resultPath);
|
|
402
|
+
return r === null ? [] : [r];
|
|
403
|
+
});
|
|
404
|
+
const report = await buildReport({ runs, missionTargetsDir: opts.missionTargetsDir });
|
|
405
|
+
const missionOutcome = combineOutcomes(missions.map((m) => m.missionOutcome));
|
|
406
|
+
const finishedAt = now();
|
|
407
|
+
const resultPath = join(outDir, "campaign.json");
|
|
408
|
+
const reportPath = join(outDir, "campaign.md");
|
|
409
|
+
const result = {
|
|
410
|
+
...(plan.name === undefined ? {} : { name: plan.name }),
|
|
411
|
+
specPath: plan.specPath,
|
|
412
|
+
outDir,
|
|
413
|
+
startedAt,
|
|
414
|
+
finishedAt,
|
|
415
|
+
discovery,
|
|
416
|
+
missions,
|
|
417
|
+
report: { defects: report.defects, summary: report.summary, runs: report.runs },
|
|
418
|
+
resultPath,
|
|
419
|
+
reportPath,
|
|
420
|
+
missionOutcome,
|
|
421
|
+
exitCode: exitCodeForOutcome(missionOutcome),
|
|
422
|
+
};
|
|
423
|
+
await writeFile(resultPath, `${JSON.stringify(result, null, 2)}\n`, "utf8");
|
|
424
|
+
await writeFile(reportPath, campaignMarkdown(result, report.markdown), "utf8");
|
|
425
|
+
return result;
|
|
426
|
+
}
|
|
427
|
+
/** The campaign's own summary (discovery, missions) above the deduped report's markdown. */
|
|
428
|
+
function campaignMarkdown(r, reportMarkdown) {
|
|
429
|
+
const lines = [
|
|
430
|
+
`# Campaign${r.name === undefined ? "" : ` — ${r.name}`}`,
|
|
431
|
+
"",
|
|
432
|
+
`${r.missions.length} anchored mission(s) · outcome ${r.missionOutcome} (exit ${r.exitCode}) · ${r.report.summary.defects} deduped defect(s), ${r.report.summary.advisory} advisory.`,
|
|
433
|
+
"",
|
|
434
|
+
"## Discovery",
|
|
435
|
+
"",
|
|
436
|
+
...(r.discovery.length === 0 ? ["Skipped (discovery: false)."] : ["| job | journey | outcome | reason |", "| --- | --- | --- | --- |", ...r.discovery.map((d) => `| ${d.job} | ${d.journeyId} | ${d.outcome} | ${(d.reason ?? "").replace(/\|/g, "\\|")} |`)]),
|
|
437
|
+
"",
|
|
438
|
+
"## Missions",
|
|
439
|
+
"",
|
|
440
|
+
"| job | branch | strategy | status | outcome | result |",
|
|
441
|
+
"| --- | --- | --- | --- | --- | --- |",
|
|
442
|
+
...r.missions.map((m) => `| ${m.job} | ${m.branch.journeyId} step ${m.branch.step}${m.branch.anchor === undefined ? "" : ` (${m.branch.anchor})`} | ${m.strategy} | ${m.status} | ${m.missionOutcome}${m.failure === undefined ? "" : ` — ${m.failure.kind}`} | ${m.resultPath === undefined ? "" : `\`${m.resultPath}\``} |`),
|
|
443
|
+
"",
|
|
444
|
+
];
|
|
445
|
+
return `${lines.join("\n")}\n${reportMarkdown.replace(/^# /, "## ").replace(/\n## /g, "\n### ")}`;
|
|
446
|
+
}
|
|
447
|
+
//# sourceMappingURL=campaign-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign-api.js","sourceRoot":"","sources":["../src/campaign-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type CliDeps } from "./cli-shared.js";
|
|
3
|
+
/** The flags every anchored mission of this `campaign run` is re-invoked with (#311). */
|
|
4
|
+
export declare function campaignMissionArgv(cmd: Command): string[];
|
|
5
|
+
/** `campaign run`'s human summary: the outcome, every mission's branch point, and the deduped defects. */
|
|
6
|
+
export declare function formatCampaignHuman(data: unknown): string;
|
|
7
|
+
/** Registers `jevitate campaign run <spec.json>` (#293). */
|
|
8
|
+
export declare function registerCampaignCommands(program: Command, deps: CliDeps, buildProgram: (deps: CliDeps) => Command): void;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ok, fail } from "./envelope.js";
|
|
2
|
+
import { withEngine } from "./engine.js";
|
|
3
|
+
import { CampaignSpecError, runCampaign, validateCampaign } from "./campaign-api.js";
|
|
4
|
+
import { emitCommandResult, environmentSeams, resolveJourneysDir, resolveMissionTargetsDir, withScreenshotsFlag } from "./cli-shared.js";
|
|
5
|
+
import { nonNegativeIntArg, positiveIntArg } from "./cli-args.js";
|
|
6
|
+
import { forwardedArgv } from "./multi-run-cli.js";
|
|
7
|
+
/** `campaign run`'s own options: everything else it declares is forwarded to every mission (#311). */
|
|
8
|
+
const CAMPAIGN_OWNED = new Set(["journeysDir", "out", "allowShellHooks", "hookTimeoutMs", "real", "fakeAi", "json"]);
|
|
9
|
+
const collect = (v, prev) => [...prev, v];
|
|
10
|
+
/** The flags every anchored mission of this `campaign run` is re-invoked with (#311). */
|
|
11
|
+
export function campaignMissionArgv(cmd) {
|
|
12
|
+
return forwardedArgv(cmd, CAMPAIGN_OWNED);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* #311: the `explore` options a campaign forwards to every anchored mission, as given — safety
|
|
16
|
+
* (destructive/paid/deny), invariants, backend-log evidence and media. Operator flags only: the
|
|
17
|
+
* spec file never widens what a mission may click or read.
|
|
18
|
+
*/
|
|
19
|
+
function withMissionFlags(cmd) {
|
|
20
|
+
const each = "(forwarded to every mission, as explore's)";
|
|
21
|
+
const repeatable = [
|
|
22
|
+
["--deny <pattern>", "a control no mission may click (repeatable)"],
|
|
23
|
+
["--paid <pattern>", "an app control that costs money or credits (repeatable)"],
|
|
24
|
+
["--invariants <file>", "app-declared invariants JSON (repeatable)"],
|
|
25
|
+
["--log-source <spec>", "backend log source: file:<path> | docker:<container> | cmd:<command> (needs --allow-log-cmd) (repeatable)"],
|
|
26
|
+
["--log-defect <level|/regex/>", "backend log lines matching this become a server-log defect (repeatable)"],
|
|
27
|
+
["--log-quiet-ok <spec>", "a --log-source that is legitimately quiet (repeatable)"],
|
|
28
|
+
["--log-ignore <regex|substring>", "known-noise backend log lines to exclude (repeatable)"],
|
|
29
|
+
["--log-scope <regex|substring>", "attribute only backend log lines matching this (repeatable)"],
|
|
30
|
+
["--log-correlation-header <name>", "another header carrying a correlation id (repeatable)"],
|
|
31
|
+
["--log-id-pattern </regex/>", "how a correlation id is written in log lines (repeatable)"],
|
|
32
|
+
];
|
|
33
|
+
for (const [flags, desc] of repeatable)
|
|
34
|
+
cmd.option(flags, `${desc} ${each}`, collect, []);
|
|
35
|
+
cmd
|
|
36
|
+
.option("--allow-destructive", `let missions click session-ending, destructive and paid controls (a --deny pattern still holds) ${each}`)
|
|
37
|
+
.option("--allow-writes", `let a find-out mission change the app ${each}`)
|
|
38
|
+
.option("--allow-log-cmd", `a --log-source cmd:<command> may run as a subprocess ${each}`)
|
|
39
|
+
.option("--log-triage", `record each mission's signal timeline and attach only the related lines to each defect (#313) ${each}`)
|
|
40
|
+
.option("--server-log-drain-ms <ms>", `how long to keep tailing --log-source after a mission's last action (default 3000) ${each}`, nonNegativeIntArg)
|
|
41
|
+
.option("--evidence-video", `per defect: a captioned repro clip and before/at screenshots ${each}`)
|
|
42
|
+
.option("--record-video [dir]", `record a video of each mission's browser context ${each}`);
|
|
43
|
+
return withScreenshotsFlag(cmd);
|
|
44
|
+
}
|
|
45
|
+
/** `campaign run`'s human summary: the outcome, every mission's branch point, and the deduped defects. */
|
|
46
|
+
export function formatCampaignHuman(data) {
|
|
47
|
+
const r = data;
|
|
48
|
+
const lines = [
|
|
49
|
+
`CAMPAIGN ${r.name ?? ""}`.trimEnd(),
|
|
50
|
+
`outcome ${r.missionOutcome} (exit ${r.exitCode}) · ${r.missions.length} mission(s) · ${r.report.summary.defects} deduped defect(s), ${r.report.summary.advisory} advisory`,
|
|
51
|
+
...r.discovery.filter((d) => d.outcome !== "ok").map((d) => `STALE job ${d.job}: journey ${d.journeyId} — ${d.reason ?? d.outcome} (its missions were skipped)`),
|
|
52
|
+
...r.missions.map((m) => `${m.status === "ran" ? "RAN" : m.status.toUpperCase()}`.padEnd(9) +
|
|
53
|
+
`${m.job} · ${m.branch.journeyId} step ${m.branch.step}${m.branch.anchor === undefined ? "" : ` (${m.branch.anchor})`} · ${m.strategy} → ${m.missionOutcome}${m.failure === undefined ? "" : ` (${m.failure.kind})`}`),
|
|
54
|
+
...r.report.defects.map((d) => `DEFECT ${d.title} · ${d.runCount} run(s)${d.branches === undefined ? "" : ` · from ${d.branches.map((b) => `${b.journeyId}@${b.anchor ?? b.step}`).join(", ")}`}`),
|
|
55
|
+
`report ${r.reportPath}`,
|
|
56
|
+
`result ${r.resultPath}`,
|
|
57
|
+
];
|
|
58
|
+
return `${lines.join("\n")}\n`;
|
|
59
|
+
}
|
|
60
|
+
/** Registers `jevitate campaign run <spec.json>` (#293). */
|
|
61
|
+
export function registerCampaignCommands(program, deps, buildProgram) {
|
|
62
|
+
const campaign = program.command("campaign").description("journey-anchored test campaigns (#293): many anchored missions, one deduped report");
|
|
63
|
+
withMissionFlags(campaign
|
|
64
|
+
.command("run <spec>"))
|
|
65
|
+
.description("run a campaign spec (JSON): replay each job's promoted Journey (discovery), then run its anchored missions in order — " +
|
|
66
|
+
"explore --from-journey <journey> --at-step <anchor> --strategy <s> — with the spec's --fixtures restore around every run, " +
|
|
67
|
+
"and write ONE deduped report (campaign.json + campaign.md). An invalid spec is refused with every problem listed (exit 64)")
|
|
68
|
+
.option("--journeys-dir <path>", "journeys directory (default: the repo's .jevitate/journeys; outside a repo ~/.jevitate/journeys)")
|
|
69
|
+
.option("--out <dir>", "the campaign's directory: every mission's results, campaign.json and campaign.md (default .jevitate/logs/<date>/campaign-<stamp>)")
|
|
70
|
+
.option("--allow-shell-hooks", "opt in to running the spec's before/after operator hooks around every run (never model-chosen)", false)
|
|
71
|
+
.option("--hook-timeout-ms <ms>", "timeout for each of the spec's before/after hooks (default 60000; the process group is killed)", positiveIntArg)
|
|
72
|
+
.option("--real", "use live Jev + OpenRouter gateways for the missions (requires keys)", false)
|
|
73
|
+
.option("--fake-ai", "use deterministic fake gateways (pipeline smoke only)", false)
|
|
74
|
+
.option("--json", "emit the JSON envelope (default: a human summary)")
|
|
75
|
+
.action(async function (spec) {
|
|
76
|
+
const o = this.opts();
|
|
77
|
+
const emit = (envelope, exitCode) => emitCommandResult(program, envelope, { json: o.json === true, command: "campaign run", human: formatCampaignHuman, ...(exitCode === undefined ? {} : { exitCode }) });
|
|
78
|
+
if (o.real !== true && o.fakeAi !== true) {
|
|
79
|
+
emit(fail("E_CAMPAIGN_ARGS", "a campaign's missions are model-driven: pass --real (live gateways) or --fake-ai (pipeline smoke only)"));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const journeysDir = resolveJourneysDir(deps, o.journeysDir);
|
|
83
|
+
try {
|
|
84
|
+
const plan = await validateCampaign(spec, {
|
|
85
|
+
journeysDir,
|
|
86
|
+
allowShellHooks: o.allowShellHooks === true,
|
|
87
|
+
...(o.hookTimeoutMs === undefined ? {} : { hookTimeoutMs: o.hookTimeoutMs }),
|
|
88
|
+
environmentSeams: environmentSeams(deps),
|
|
89
|
+
});
|
|
90
|
+
const result = await runCampaign(plan, {
|
|
91
|
+
newProgram: () => buildProgram(deps),
|
|
92
|
+
journeysDir,
|
|
93
|
+
missionTargetsDir: resolveMissionTargetsDir(deps),
|
|
94
|
+
...(o.out === undefined ? {} : { outDir: o.out }),
|
|
95
|
+
...(o.real === true ? { real: true } : {}),
|
|
96
|
+
...(o.fakeAi === true ? { fakeAi: true } : {}),
|
|
97
|
+
missionArgs: campaignMissionArgv(this),
|
|
98
|
+
});
|
|
99
|
+
emit(ok(withEngine(result)), result.exitCode);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
if (err instanceof CampaignSpecError)
|
|
103
|
+
emit(fail(err.code, err.message));
|
|
104
|
+
else
|
|
105
|
+
emit(fail("E_CAMPAIGN_RUN", String(err instanceof Error ? err.message : err)));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=campaign-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign-cli.js","sourceRoot":"","sources":["../src/campaign-cli.ts"],"names":[],"mappings":"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"}
|