@jevitate/cli 0.16.1 → 0.17.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 +55 -5
- package/dist/bin.js +473 -83
- package/dist/build-info.generated.js +3 -3
- package/dist/exit-codes.js +1 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/journey-api.d.ts +8 -0
- package/dist/journey-api.js +9 -2
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-chain.d.ts +92 -0
- package/dist/journey-chain.js +200 -0
- package/dist/journey-chain.js.map +1 -0
- package/dist/journey-cli/chain.d.ts +8 -0
- package/dist/journey-cli/chain.js +106 -0
- package/dist/journey-cli/chain.js.map +1 -0
- package/dist/journey-cli.d.ts +1 -1
- package/dist/journey-cli.js +4 -1
- package/dist/journey-cli.js.map +1 -1
- package/dist/journey-verify.d.ts +2 -0
- package/dist/journey-verify.js +14 -1
- package/dist/journey-verify.js.map +1 -1
- package/dist/mcp-cli-tools.js +23 -0
- package/dist/mcp-cli-tools.js.map +1 -1
- package/package.json +8 -8
package/dist/bin.js
CHANGED
|
@@ -31320,6 +31320,8 @@ var USAGE_ERROR_PATTERNS = [
|
|
|
31320
31320
|
var USAGE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
31321
31321
|
"E_CHECK_SUITE",
|
|
31322
31322
|
// the suite (or its preflight) was refused
|
|
31323
|
+
"E_CHAIN_REQUEST",
|
|
31324
|
+
// #580: an approved-requests line is malformed or carries an unknown key — nothing ran
|
|
31323
31325
|
"E_CAMPAIGN_PREFLIGHT",
|
|
31324
31326
|
// #485: a campaign's preconditions failed (start URL, session, allow list) — no mission ran
|
|
31325
31327
|
"E_AI_SETUP_REQUIRED",
|
|
@@ -35996,11 +35998,31 @@ async function waitForOutcome(actor, expect, wait, step) {
|
|
|
35996
35998
|
}
|
|
35997
35999
|
|
|
35998
36000
|
// ../interpreter/dist/run-step.js
|
|
36001
|
+
var SelectAlternativeUnavailableError = class extends Error {
|
|
36002
|
+
constructor() {
|
|
36003
|
+
super("no-alternative: the select has no enabled option other than the one this proof avoids");
|
|
36004
|
+
this.name = "SelectAlternativeUnavailableError";
|
|
36005
|
+
}
|
|
36006
|
+
};
|
|
35999
36007
|
async function strictTarget(actor, d, opts) {
|
|
36000
36008
|
const page = actor.ability(BrowseTheWebToken).session.page;
|
|
36001
36009
|
const locator = await resolveTarget(page, d, opts);
|
|
36002
36010
|
return Target.named(descriptorToTarget(d).description).locatedBy(() => locator);
|
|
36003
36011
|
}
|
|
36012
|
+
async function selectAlternativeValue(locator, avoid) {
|
|
36013
|
+
const value = await locator.evaluate((el, avoided) => {
|
|
36014
|
+
const options = el.options ?? [];
|
|
36015
|
+
for (let i = 0; i < options.length; i += 1) {
|
|
36016
|
+
const option = options[i];
|
|
36017
|
+
if (!option.disabled && option.value !== "" && option.value !== avoided)
|
|
36018
|
+
return option.value;
|
|
36019
|
+
}
|
|
36020
|
+
return null;
|
|
36021
|
+
}, avoid);
|
|
36022
|
+
if (value === null)
|
|
36023
|
+
throw new SelectAlternativeUnavailableError();
|
|
36024
|
+
return value;
|
|
36025
|
+
}
|
|
36004
36026
|
function resolveValue(value, vars) {
|
|
36005
36027
|
if ("var" in value) {
|
|
36006
36028
|
const v = vars.get(value.var);
|
|
@@ -36101,9 +36123,12 @@ async function runStep(actor, rec, vars, index = 0, targetOpts = {}) {
|
|
|
36101
36123
|
return { kind: "done" };
|
|
36102
36124
|
}
|
|
36103
36125
|
case "select": {
|
|
36104
|
-
const
|
|
36126
|
+
const alternative = targetOpts.selectAlternative?.(index);
|
|
36127
|
+
const chosen = alternative === void 0 ? resolveValue(step.value, vars) : void 0;
|
|
36105
36128
|
const page = actor.ability(BrowseTheWebToken).session.page;
|
|
36106
|
-
|
|
36129
|
+
const locator = await resolveTarget(page, step.target, targetOpts);
|
|
36130
|
+
const value = chosen ?? await selectAlternativeValue(locator, alternative.avoid);
|
|
36131
|
+
await locator.selectOption(value);
|
|
36107
36132
|
await postcondition(actor, expected(step.expect), step.waitFor, "select", index, targetOpts);
|
|
36108
36133
|
return { kind: "done" };
|
|
36109
36134
|
}
|
|
@@ -36150,8 +36175,14 @@ async function runStep(actor, rec, vars, index = 0, targetOpts = {}) {
|
|
|
36150
36175
|
vars.set(`${step.as}.__index`, String(i));
|
|
36151
36176
|
for (const childStep of step.steps) {
|
|
36152
36177
|
await runRowScopedChildStep(actor, childStep, rowLocator, vars, expected);
|
|
36178
|
+
if (childStep.kind === "extract") {
|
|
36179
|
+
const value = vars.get(childStep.as);
|
|
36180
|
+
if (value !== void 0)
|
|
36181
|
+
vars.set(`${step.as}.${i}.${childStep.as}`, value);
|
|
36182
|
+
}
|
|
36153
36183
|
}
|
|
36154
36184
|
}
|
|
36185
|
+
vars.set(`${step.as}.count`, String(count));
|
|
36155
36186
|
return { kind: "done" };
|
|
36156
36187
|
}
|
|
36157
36188
|
case "handback": {
|
|
@@ -36266,6 +36297,7 @@ var RecordingInterpreter = class {
|
|
|
36266
36297
|
...this.options.targetTimeoutMs === void 0 ? {} : { timeoutMs: this.options.targetTimeoutMs },
|
|
36267
36298
|
...this.options.observer === void 0 ? {} : { observer: this.options.observer },
|
|
36268
36299
|
...this.options.skipStep === void 0 ? {} : { skipStep: this.options.skipStep },
|
|
36300
|
+
...this.options.selectAlternative === void 0 ? {} : { selectAlternative: this.options.selectAlternative },
|
|
36269
36301
|
...this.options.fixtureBaseDir === void 0 ? {} : { fixtureBaseDir: this.options.fixtureBaseDir },
|
|
36270
36302
|
...this.options.refLookup === void 0 ? {} : { refLookup: this.options.refLookup }
|
|
36271
36303
|
};
|
|
@@ -53506,7 +53538,7 @@ function assertionSiteKey(site) {
|
|
|
53506
53538
|
return `step-request:${site.step}:${site.checkIndex}`;
|
|
53507
53539
|
return `end-state:${site.index}`;
|
|
53508
53540
|
}
|
|
53509
|
-
var MUTATION_RE = /^(skip|block-write|stale-value|swap-param|truncate-param):(.+)$/;
|
|
53541
|
+
var MUTATION_RE = /^(skip|block-write|stale-value|swap-param|truncate-param|guard-param):(.+)$/;
|
|
53510
53542
|
var SITE_RE = /^(?:step:[1-9][0-9]*|step-request:[1-9][0-9]*:(?:0|[1-9][0-9]*)|end-state:(?:0|[1-9][0-9]*))$/;
|
|
53511
53543
|
function flat(journey) {
|
|
53512
53544
|
return journey.recording.pages.flatMap((p) => p.steps);
|
|
@@ -53518,15 +53550,36 @@ function firstActionStep(journey, name) {
|
|
|
53518
53550
|
const i = flat(journey).findIndex((r) => actionRefs(r.step).includes(name));
|
|
53519
53551
|
return i < 0 ? null : i + 1;
|
|
53520
53552
|
}
|
|
53553
|
+
function allActionReadsAreSelect(journey, name) {
|
|
53554
|
+
const reads2 = flat(journey).filter((r) => actionRefs(r.step).includes(name));
|
|
53555
|
+
return reads2.length > 0 && reads2.every((r) => r.step.kind === "select");
|
|
53556
|
+
}
|
|
53557
|
+
function reviewedValue(journey, name, supplied) {
|
|
53558
|
+
const declared = (journey.metadata.parameters ?? []).find((p) => p.name === name);
|
|
53559
|
+
return declared?.mutationValues?.find((v) => v !== supplied) ?? null;
|
|
53560
|
+
}
|
|
53561
|
+
function selectsVar(step, name) {
|
|
53562
|
+
return step.kind === "select" && "var" in step.value && step.value.var === name;
|
|
53563
|
+
}
|
|
53521
53564
|
function paramMutation(kind, step, param) {
|
|
53522
53565
|
return { kind, step, id: `${kind}:${param}`, param };
|
|
53523
53566
|
}
|
|
53567
|
+
function guardSites(journey, sites, name) {
|
|
53568
|
+
const action = firstActionStep(journey, name);
|
|
53569
|
+
return sites.filter((s3) => s3.where === "step" && siteRefs(s3).includes(name) && (action === null || s3.step < action));
|
|
53570
|
+
}
|
|
53524
53571
|
function paramMutationRef(journey, kind, name, value) {
|
|
53525
53572
|
const declared = [...journey.metadata.params, ...(journey.metadata.parameters ?? []).map((p) => p.name)];
|
|
53526
53573
|
if (!declared.includes(name))
|
|
53527
53574
|
throw new Error(`${JSON.stringify(value)}: ${JSON.stringify(name)} is not a declared parameter`);
|
|
53528
53575
|
if (secretParamNames(journey).includes(name))
|
|
53529
53576
|
throw new Error(`${JSON.stringify(value)}: ${name} is a secret parameter \u2014 a secret is never mutated`);
|
|
53577
|
+
if (kind === "guard-param") {
|
|
53578
|
+
const first = guardSites(journey, journeyAssertions(journey), name)[0];
|
|
53579
|
+
if (first === void 0)
|
|
53580
|
+
throw new Error(`${JSON.stringify(value)}: no step assertion checks ${name} before an action reads it`);
|
|
53581
|
+
return paramMutation(kind, first.step, name);
|
|
53582
|
+
}
|
|
53530
53583
|
const step = firstActionStep(journey, name);
|
|
53531
53584
|
if (step === null)
|
|
53532
53585
|
throw new Error(`${JSON.stringify(value)}: no step's action reads ${name} (a fill or a navigate URL)`);
|
|
@@ -53535,9 +53588,9 @@ function paramMutationRef(journey, kind, name, value) {
|
|
|
53535
53588
|
function resolveMutationRef(journey, value) {
|
|
53536
53589
|
const m = MUTATION_RE.exec(value.trim());
|
|
53537
53590
|
if (m === null)
|
|
53538
|
-
throw new Error(`${JSON.stringify(value)} is not a mutation \u2014 expected skip:<step>, block-write:<step> or stale-value:<step> (a step number or an anchor name), or swap-param:<param> / truncate-param:<param>`);
|
|
53591
|
+
throw new Error(`${JSON.stringify(value)} is not a mutation \u2014 expected skip:<step>, block-write:<step> or stale-value:<step> (a step number or an anchor name), or swap-param:<param> / truncate-param:<param> / guard-param:<param>`);
|
|
53539
53592
|
const ref = m[2];
|
|
53540
|
-
if (m[1] === "swap-param" || m[1] === "truncate-param")
|
|
53593
|
+
if (m[1] === "swap-param" || m[1] === "truncate-param" || m[1] === "guard-param")
|
|
53541
53594
|
return paramMutationRef(journey, m[1], ref, value);
|
|
53542
53595
|
let step;
|
|
53543
53596
|
try {
|
|
@@ -53653,17 +53706,30 @@ function planJourneyMutations(journey, opts = {}) {
|
|
|
53653
53706
|
const params = opts.params ?? {};
|
|
53654
53707
|
const names = [...new Set(sites.flatMap(siteRefs))];
|
|
53655
53708
|
for (const name of names) {
|
|
53709
|
+
const supplied = mutableParamValue(journey, name, params);
|
|
53710
|
+
const guards = guardSites(journey, sites, name);
|
|
53711
|
+
const guardValue = supplied === null ? null : reviewedValue(journey, name, supplied) ?? swappedValue(journey, name, params);
|
|
53712
|
+
if (guards.length > 0 && guardValue !== null) {
|
|
53713
|
+
const g = { ...paramMutation("guard-param", guards[0].step, name), source: reviewedValue(journey, name, supplied) === null ? "generated" : "reviewed" };
|
|
53714
|
+
mutations.push(g);
|
|
53715
|
+
for (const s3 of guards)
|
|
53716
|
+
pair(s3, g);
|
|
53717
|
+
}
|
|
53656
53718
|
const at3 = firstActionStep(journey, name);
|
|
53657
53719
|
if (at3 === null)
|
|
53658
53720
|
continue;
|
|
53659
|
-
const naming = sites.filter((s3) => siteRefs(s3).includes(name));
|
|
53660
|
-
|
|
53721
|
+
const naming = sites.filter((s3) => siteRefs(s3).includes(name) && !guards.includes(s3));
|
|
53722
|
+
if (naming.length === 0)
|
|
53723
|
+
continue;
|
|
53724
|
+
const candidates = [
|
|
53661
53725
|
["swap-param", swappedValue(journey, name, params)],
|
|
53662
|
-
["truncate-param", truncatedValue(journey, name, params)]
|
|
53663
|
-
]
|
|
53726
|
+
...allActionReadsAreSelect(journey, name) ? [] : [["truncate-param", truncatedValue(journey, name, params)]]
|
|
53727
|
+
];
|
|
53728
|
+
const source = supplied !== null && reviewedValue(journey, name, supplied) !== null ? "reviewed" : allActionReadsAreSelect(journey, name) ? "option" : "generated";
|
|
53729
|
+
for (const [kind, value] of candidates) {
|
|
53664
53730
|
if (value === null)
|
|
53665
53731
|
continue;
|
|
53666
|
-
const m = paramMutation(kind, at3, name);
|
|
53732
|
+
const m = kind === "swap-param" ? { ...paramMutation(kind, at3, name), source } : paramMutation(kind, at3, name);
|
|
53667
53733
|
mutations.push(m);
|
|
53668
53734
|
for (const s3 of naming)
|
|
53669
53735
|
pair(s3, m);
|
|
@@ -53686,7 +53752,7 @@ function mutationWait(wait) {
|
|
|
53686
53752
|
var MUTATION_WAIT_MARGIN_MS = 5e3;
|
|
53687
53753
|
function mutationReplay(journey, m, opts = {}) {
|
|
53688
53754
|
const index = m.step - 1;
|
|
53689
|
-
if (m.kind === "swap-param" || m.kind === "truncate-param")
|
|
53755
|
+
if (m.kind === "swap-param" || m.kind === "truncate-param" || m.kind === "guard-param")
|
|
53690
53756
|
return paramReplay(journey, m, opts.params ?? {});
|
|
53691
53757
|
if (m.kind === "block-write") {
|
|
53692
53758
|
const requests = journeyWriteSteps(journey, opts).find((w) => w.step === m.step)?.requests ?? [];
|
|
@@ -53719,6 +53785,25 @@ function mutationReplay(journey, m, opts = {}) {
|
|
|
53719
53785
|
}
|
|
53720
53786
|
function paramReplay(journey, m, params) {
|
|
53721
53787
|
const name = m.param ?? "";
|
|
53788
|
+
const index = m.step - 1;
|
|
53789
|
+
const target = flat(journey)[index]?.step;
|
|
53790
|
+
if (m.kind === "guard-param") {
|
|
53791
|
+
const supplied2 = mutableParamValue(journey, name, params);
|
|
53792
|
+
const wrong = supplied2 === null ? null : reviewedValue(journey, name, supplied2) ?? swappedValue(journey, name, params);
|
|
53793
|
+
if (wrong === null)
|
|
53794
|
+
throw new Error(`${m.id}: parameter ${name} has no value this proof may alter (not supplied, blank, too short, or secret)`);
|
|
53795
|
+
return { journey, params: { ...params, [name]: wrong } };
|
|
53796
|
+
}
|
|
53797
|
+
const reviewedFrom = m.kind === "swap-param" ? mutableParamValue(journey, name, params) : null;
|
|
53798
|
+
const reviewed = reviewedFrom === null ? null : reviewedValue(journey, name, reviewedFrom);
|
|
53799
|
+
if (reviewedFrom !== null && reviewed !== null)
|
|
53800
|
+
return { journey: pinAssertionRefs(journey, name, reviewedFrom), params: { ...params, [name]: reviewed } };
|
|
53801
|
+
if (m.kind === "swap-param" && target !== void 0 && selectsVar(target, name)) {
|
|
53802
|
+
const supplied2 = mutableParamValue(journey, name, params);
|
|
53803
|
+
if (supplied2 === null)
|
|
53804
|
+
throw new Error(`${m.id}: parameter ${name} has no value this proof may alter (not supplied, blank, too short, or secret)`);
|
|
53805
|
+
return { journey: structuredClone(journey), swapSelectAtStep: { index, avoid: supplied2 } };
|
|
53806
|
+
}
|
|
53722
53807
|
const supplied = mutableParamValue(journey, name, params);
|
|
53723
53808
|
const altered = m.kind === "swap-param" ? swappedValue(journey, name, params) : truncatedValue(journey, name, params);
|
|
53724
53809
|
if (supplied === null || altered === null)
|
|
@@ -53734,7 +53819,7 @@ function relaxedMutationReplay(journey, m, opts = {}) {
|
|
|
53734
53819
|
const index = m.step - 1;
|
|
53735
53820
|
if (m.kind === "skip")
|
|
53736
53821
|
return { journey, skipIndex: index };
|
|
53737
|
-
if (m.kind === "swap-param" || m.kind === "truncate-param") {
|
|
53822
|
+
if (m.kind === "swap-param" || m.kind === "truncate-param" || m.kind === "guard-param") {
|
|
53738
53823
|
const how = paramReplay(journey, m, opts.params ?? {});
|
|
53739
53824
|
const target2 = flat(how.journey)[index];
|
|
53740
53825
|
if (target2 !== void 0 && "expect" in target2.step) {
|
|
@@ -53987,7 +54072,9 @@ var JourneySuccessCriterionSchema = external_exports.object({
|
|
|
53987
54072
|
var JourneyParameterSchema = external_exports.object({
|
|
53988
54073
|
name: external_exports.string().min(1).max(200),
|
|
53989
54074
|
description: external_exports.string().max(2e3).optional(),
|
|
53990
|
-
secret: external_exports.boolean().optional()
|
|
54075
|
+
secret: external_exports.boolean().optional(),
|
|
54076
|
+
// #579: reviewed, non-secret alternative values — at most 20 distinct 1..2000-char strings.
|
|
54077
|
+
mutationValues: external_exports.array(TEXT).min(1).max(20).refine((vs) => new Set(vs).size === vs.length, { message: "mutationValues: duplicate value" }).optional()
|
|
53991
54078
|
}).strict();
|
|
53992
54079
|
var CATALOG_REF_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
53993
54080
|
var CatalogRefSchema = external_exports.string().regex(CATALOG_REF_RE, "a catalog id: 1-64 of [A-Za-z0-9._-], starting alphanumeric");
|
|
@@ -54072,6 +54159,17 @@ var JourneySchema = external_exports.object({
|
|
|
54072
54159
|
}));
|
|
54073
54160
|
for (const issue3 of assertionRefIssues(j))
|
|
54074
54161
|
ctx.addIssue({ code: "custom", path: [...issue3.path], message: issue3.message });
|
|
54162
|
+
(j.metadata.parameters ?? []).forEach((p, i) => {
|
|
54163
|
+
if (p.mutationValues === void 0)
|
|
54164
|
+
return;
|
|
54165
|
+
if (p.secret === true || SECRET_PARAM_NAME_RE2.test(p.name)) {
|
|
54166
|
+
ctx.addIssue({
|
|
54167
|
+
code: "custom",
|
|
54168
|
+
path: ["metadata", "parameters", i, "mutationValues"],
|
|
54169
|
+
message: `E_MUTATION_VALUES_SECRET: parameter "${p.name}" is a secret (secret: true or a credential-like name) \u2014 mutationValues are reviewed, non-secret values and may never carry a credential`
|
|
54170
|
+
});
|
|
54171
|
+
}
|
|
54172
|
+
});
|
|
54075
54173
|
});
|
|
54076
54174
|
function ownAssertions(step) {
|
|
54077
54175
|
if (step.kind === "assert")
|
|
@@ -54305,6 +54403,9 @@ function journeyParamSchema(journey) {
|
|
|
54305
54403
|
};
|
|
54306
54404
|
for (const page of journey.recording.pages) {
|
|
54307
54405
|
for (const { step } of page.steps) {
|
|
54406
|
+
for (const name of actionRefs(step))
|
|
54407
|
+
if (declared.has(name) && !extracted.has(name) && !required2.includes(name))
|
|
54408
|
+
required2.push(name);
|
|
54308
54409
|
if (step.kind === "extract")
|
|
54309
54410
|
extracted.add(step.as);
|
|
54310
54411
|
for (const { assertion } of ownAssertions(step))
|
|
@@ -61887,9 +61988,9 @@ function hostStarvedFailure(failure3, health) {
|
|
|
61887
61988
|
}
|
|
61888
61989
|
|
|
61889
61990
|
// src/build-info.generated.ts
|
|
61890
|
-
var GENERATED_COMMIT = "
|
|
61891
|
-
var GENERATED_TREE = "
|
|
61892
|
-
var GENERATED_BUILT_AT = "2026-10-
|
|
61991
|
+
var GENERATED_COMMIT = "89237bd";
|
|
61992
|
+
var GENERATED_TREE = "b6b4c8d";
|
|
61993
|
+
var GENERATED_BUILT_AT = "2026-10-18T16:47:05.375Z";
|
|
61893
61994
|
|
|
61894
61995
|
// src/version.ts
|
|
61895
61996
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
@@ -61911,13 +62012,13 @@ function readCliVersion() {
|
|
|
61911
62012
|
|
|
61912
62013
|
// src/engine.ts
|
|
61913
62014
|
function bundledCommit() {
|
|
61914
|
-
return true ? "
|
|
62015
|
+
return true ? "89237bd" : void 0;
|
|
61915
62016
|
}
|
|
61916
62017
|
function bundledBuiltAt() {
|
|
61917
|
-
return true ? "2026-10-
|
|
62018
|
+
return true ? "2026-10-18T16:47:05.375Z" : void 0;
|
|
61918
62019
|
}
|
|
61919
62020
|
function bundledTree() {
|
|
61920
|
-
return true ? "
|
|
62021
|
+
return true ? "b6b4c8d" : void 0;
|
|
61921
62022
|
}
|
|
61922
62023
|
function currentBuildTree() {
|
|
61923
62024
|
return bundledTree() ?? GENERATED_TREE;
|
|
@@ -80255,13 +80356,13 @@ import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir8, rm as
|
|
|
80255
80356
|
import { homedir as realHomedir } from "node:os";
|
|
80256
80357
|
import { join as join19, dirname as dirname6 } from "node:path";
|
|
80257
80358
|
function detectRuntimes(deps = {}) {
|
|
80258
|
-
const
|
|
80359
|
+
const existsSync47 = deps.existsSync ?? realExistsSync;
|
|
80259
80360
|
const homedir6 = deps.homedir ?? realHomedir;
|
|
80260
80361
|
const cwd = deps.cwd ?? process.cwd;
|
|
80261
80362
|
const detected = [];
|
|
80262
|
-
if (
|
|
80263
|
-
if (
|
|
80264
|
-
if (
|
|
80363
|
+
if (existsSync47(join19(homedir6(), ".claude"))) detected.push("claude-code");
|
|
80364
|
+
if (existsSync47(join19(homedir6(), ".codex"))) detected.push("codex");
|
|
80365
|
+
if (existsSync47(join19(cwd(), ".cursor"))) detected.push("cursor");
|
|
80265
80366
|
detected.push("generic");
|
|
80266
80367
|
return detected;
|
|
80267
80368
|
}
|
|
@@ -94313,8 +94414,15 @@ async function runJourneyProgrammatically(opts, mutation2 = {}) {
|
|
|
94313
94414
|
shots === void 0 ? void 0 : screenshotObserver(shots, (a) => a.ability(BrowseTheWebToken).session.page, whatOf)
|
|
94314
94415
|
);
|
|
94315
94416
|
const skipStep = mutation2.skipStep;
|
|
94417
|
+
const selectAlternative = mutation2.selectAlternativeAtStep;
|
|
94316
94418
|
const fixtureBaseDir = opts.fixtureBaseDir ?? journeyFixtureBaseDir();
|
|
94317
|
-
const interpreter = opts.interpreter ?? (opts.observer === void 0 && shots === void 0 && replayDeltas === void 0 && outcomeChecks.observer() === void 0 && blocker === void 0 && healGuard === void 0 && skipStep === void 0 ? new RecordingInterpreter({ fixtureBaseDir, refLookup: refs }) : new RecordingInterpreter({
|
|
94419
|
+
const interpreter = opts.interpreter ?? (opts.observer === void 0 && shots === void 0 && replayDeltas === void 0 && outcomeChecks.observer() === void 0 && blocker === void 0 && healGuard === void 0 && skipStep === void 0 && selectAlternative === void 0 ? new RecordingInterpreter({ fixtureBaseDir, refLookup: refs }) : new RecordingInterpreter({
|
|
94420
|
+
observer,
|
|
94421
|
+
fixtureBaseDir,
|
|
94422
|
+
refLookup: refs,
|
|
94423
|
+
...skipStep === void 0 ? {} : { skipStep: (i) => skipStep(i) },
|
|
94424
|
+
...selectAlternative === void 0 ? {} : { selectAlternative: (i) => i === selectAlternative.index ? { avoid: selectAlternative.avoid } : void 0 }
|
|
94425
|
+
}));
|
|
94318
94426
|
const heal = opts.heal === void 0 || healGuard === void 0 ? void 0 : { scope: opts.heal.scope, riskOf: journeyStepRisk(), writeGuard: healGuard.guard, allowedOrigins, observe: healObserver(healDir, mask) };
|
|
94319
94427
|
const runner = new JourneyRunner(actor, interpreter, void 0, void 0, opts.selfHealer, heal);
|
|
94320
94428
|
let result;
|
|
@@ -107504,6 +107612,249 @@ function registerJourneyRun(journey, program2, deps) {
|
|
|
107504
107612
|
}));
|
|
107505
107613
|
}
|
|
107506
107614
|
|
|
107615
|
+
// src/journey-cli/chain.ts
|
|
107616
|
+
import { existsSync as existsSync27, readFileSync as readFileSync33 } from "node:fs";
|
|
107617
|
+
|
|
107618
|
+
// src/journey-chain.ts
|
|
107619
|
+
var JourneyChainError = class extends Error {
|
|
107620
|
+
code;
|
|
107621
|
+
constructor(code, message2) {
|
|
107622
|
+
super(message2);
|
|
107623
|
+
this.name = "JourneyChainError";
|
|
107624
|
+
this.code = code;
|
|
107625
|
+
}
|
|
107626
|
+
};
|
|
107627
|
+
var E_CHAIN_FIELD = "E_CHAIN_FIELD";
|
|
107628
|
+
var REQUEST_KEYS = ["commentId", "account", "replyText"];
|
|
107629
|
+
function parseChainRequests(text2) {
|
|
107630
|
+
const requests = [];
|
|
107631
|
+
const lines = text2.split(/\r?\n/);
|
|
107632
|
+
for (let n3 = 0; n3 < lines.length; n3++) {
|
|
107633
|
+
const line2 = lines[n3]?.trim() ?? "";
|
|
107634
|
+
if (line2 === "") continue;
|
|
107635
|
+
let parsed;
|
|
107636
|
+
try {
|
|
107637
|
+
parsed = JSON.parse(line2);
|
|
107638
|
+
} catch {
|
|
107639
|
+
throw new JourneyChainError("E_CHAIN_REQUEST", `request line ${n3 + 1} is not valid JSON`);
|
|
107640
|
+
}
|
|
107641
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
107642
|
+
throw new JourneyChainError("E_CHAIN_REQUEST", `request line ${n3 + 1} must be a JSON object`);
|
|
107643
|
+
}
|
|
107644
|
+
const bag = parsed;
|
|
107645
|
+
const keys = Object.keys(bag);
|
|
107646
|
+
const missing = REQUEST_KEYS.filter((k) => !keys.includes(k));
|
|
107647
|
+
const extra = keys.filter((k) => !REQUEST_KEYS.includes(k));
|
|
107648
|
+
if (missing.length > 0 || extra.length > 0) {
|
|
107649
|
+
throw new JourneyChainError("E_CHAIN_REQUEST", `request line ${n3 + 1} \u2014 missing: [${missing.join(", ")}], unknown: [${extra.join(", ")}]`);
|
|
107650
|
+
}
|
|
107651
|
+
for (const k of REQUEST_KEYS) {
|
|
107652
|
+
if (typeof bag[k] !== "string") {
|
|
107653
|
+
throw new JourneyChainError("E_CHAIN_REQUEST", `request line ${n3 + 1} \u2014 ${k} must be a string`);
|
|
107654
|
+
}
|
|
107655
|
+
}
|
|
107656
|
+
requests.push({ commentId: bag.commentId, account: bag.account, replyText: bag.replyText });
|
|
107657
|
+
}
|
|
107658
|
+
return requests;
|
|
107659
|
+
}
|
|
107660
|
+
var recordKey2 = (commentId, account) => `${commentId}\0${account}`;
|
|
107661
|
+
var asString = (v) => typeof v === "string" && v !== "" ? v : void 0;
|
|
107662
|
+
function readRecords(output3) {
|
|
107663
|
+
const bag = output3 !== null && typeof output3 === "object" ? output3 : {};
|
|
107664
|
+
const raw = bag["records.count"];
|
|
107665
|
+
const count = typeof raw === "string" ? Number.parseInt(raw, 10) : Number.NaN;
|
|
107666
|
+
if (!Number.isInteger(count) || count <= 0) {
|
|
107667
|
+
throw new JourneyChainError("E_CHAIN_EMPTY", `the discover Journey returned no records (records.count = ${raw === void 0 ? "missing" : JSON.stringify(raw)})`);
|
|
107668
|
+
}
|
|
107669
|
+
const field3 = (i, name) => asString(bag[`records.${i}.${name}`]);
|
|
107670
|
+
const records = Array.from({ length: count }, (_, i) => ({
|
|
107671
|
+
commentId: field3(i, "commentId"),
|
|
107672
|
+
account: field3(i, "account"),
|
|
107673
|
+
threadId: field3(i, "threadId"),
|
|
107674
|
+
sourceText: field3(i, "sourceText"),
|
|
107675
|
+
parentId: field3(i, "parentId")
|
|
107676
|
+
}));
|
|
107677
|
+
return { count, records };
|
|
107678
|
+
}
|
|
107679
|
+
function chainParams(record2, request, declared) {
|
|
107680
|
+
const sources = {
|
|
107681
|
+
commentId: record2.commentId,
|
|
107682
|
+
replyIdentity: record2.account,
|
|
107683
|
+
threadId: record2.threadId,
|
|
107684
|
+
expected_commentid: record2.commentId,
|
|
107685
|
+
expected_account: record2.account,
|
|
107686
|
+
expected_sourcetext: record2.sourceText,
|
|
107687
|
+
expected_parentid: record2.parentId
|
|
107688
|
+
};
|
|
107689
|
+
const params = { replyText: request.replyText };
|
|
107690
|
+
for (const [name, value] of Object.entries(sources)) {
|
|
107691
|
+
if (!declared.has(name)) continue;
|
|
107692
|
+
if (value === void 0) return { ok: false, detail: `E_CHAIN_FIELD: the record has no value for ${name}` };
|
|
107693
|
+
params[name] = value;
|
|
107694
|
+
}
|
|
107695
|
+
return { ok: true, params };
|
|
107696
|
+
}
|
|
107697
|
+
var TEXT_PARAMS = ["replyText", "expected_sourcetext"];
|
|
107698
|
+
function redactReason(reason, params) {
|
|
107699
|
+
let out = reason;
|
|
107700
|
+
for (const name of TEXT_PARAMS) {
|
|
107701
|
+
const value = params[name];
|
|
107702
|
+
if (value === void 0 || value === "") continue;
|
|
107703
|
+
for (const form of /* @__PURE__ */ new Set([value, JSON.stringify(value).slice(1, -1)])) out = out.split(form).join(`<param ${name}>`);
|
|
107704
|
+
}
|
|
107705
|
+
return out;
|
|
107706
|
+
}
|
|
107707
|
+
function chainSucceeded(result) {
|
|
107708
|
+
return result.unmatched.length === 0 && result.runs.every((run) => run.outcome === "ok");
|
|
107709
|
+
}
|
|
107710
|
+
function sharedRunOptions(opts) {
|
|
107711
|
+
return {
|
|
107712
|
+
dir: opts.dir,
|
|
107713
|
+
...opts.environment === void 0 ? {} : { environment: opts.environment },
|
|
107714
|
+
...opts.storageState === void 0 ? {} : { storageState: opts.storageState },
|
|
107715
|
+
...opts.browser === void 0 ? {} : { browser: opts.browser },
|
|
107716
|
+
...opts.emulation === void 0 ? {} : { emulation: opts.emulation },
|
|
107717
|
+
...opts.browserPortFactory === void 0 ? {} : { browserPortFactory: opts.browserPortFactory },
|
|
107718
|
+
...opts.allow === void 0 ? {} : { allow: opts.allow },
|
|
107719
|
+
...opts.siteGate === void 0 ? {} : { siteGate: opts.siteGate }
|
|
107720
|
+
};
|
|
107721
|
+
}
|
|
107722
|
+
async function runJourneyChain(opts, deps = {}) {
|
|
107723
|
+
const requests = parseChainRequests(opts.requests);
|
|
107724
|
+
const runner = deps.runJourney ?? runJourneyProgrammatically;
|
|
107725
|
+
const shared3 = sharedRunOptions(opts);
|
|
107726
|
+
const registry3 = new JourneyRegistry(new FsJourneyStore(opts.dir));
|
|
107727
|
+
const toJourney = await registry3.get(opts.to);
|
|
107728
|
+
if (toJourney === null) throw new UnknownJourneyError(`unknown journey '${opts.to}'`);
|
|
107729
|
+
if (opts.requirePromoted === true) {
|
|
107730
|
+
const fromJourney = await registry3.get(opts.from);
|
|
107731
|
+
if (fromJourney === null) throw new UnknownJourneyError(`unknown journey '${opts.from}'`);
|
|
107732
|
+
for (const j of [fromJourney, toJourney]) {
|
|
107733
|
+
if (!j.metadata.promoted) throw new JourneyChainError("E_CHAIN_NOT_PROMOTED", `journey '${j.metadata.id}' is not promoted \u2014 a chain runs promoted Journeys (journey chain --allow-draft runs drafts on the CLI)`);
|
|
107734
|
+
}
|
|
107735
|
+
}
|
|
107736
|
+
const fromResult = await runner({ ...shared3, id: opts.from, params: {} });
|
|
107737
|
+
if (fromResult.outcome !== "ok") {
|
|
107738
|
+
const reason = "reason" in fromResult ? fromResult.reason : void 0;
|
|
107739
|
+
throw new JourneyChainError(
|
|
107740
|
+
"E_CHAIN_FROM_FAILED",
|
|
107741
|
+
`discover Journey '${opts.from}' did not run ok (${fromResult.outcome})${reason === void 0 ? "" : `: ${reason}`}`
|
|
107742
|
+
);
|
|
107743
|
+
}
|
|
107744
|
+
const { count, records } = readRecords(fromResult.output);
|
|
107745
|
+
const declared = new Set(journeyParamSchema(toJourney).required);
|
|
107746
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
107747
|
+
for (const record2 of records) {
|
|
107748
|
+
if (record2.commentId !== void 0 && record2.account !== void 0) byKey.set(recordKey2(record2.commentId, record2.account), record2);
|
|
107749
|
+
}
|
|
107750
|
+
const runs = [];
|
|
107751
|
+
const unmatched = [];
|
|
107752
|
+
for (const request of requests) {
|
|
107753
|
+
const record2 = byKey.get(recordKey2(request.commentId, request.account));
|
|
107754
|
+
if (record2 === void 0) {
|
|
107755
|
+
unmatched.push({ commentId: request.commentId, account: request.account });
|
|
107756
|
+
continue;
|
|
107757
|
+
}
|
|
107758
|
+
const mapped = chainParams(record2, request, declared);
|
|
107759
|
+
if (!mapped.ok) {
|
|
107760
|
+
runs.push({ commentId: request.commentId, account: request.account, outcome: E_CHAIN_FIELD, reason: mapped.detail });
|
|
107761
|
+
continue;
|
|
107762
|
+
}
|
|
107763
|
+
try {
|
|
107764
|
+
const result = await runner({ ...shared3, id: opts.to, params: mapped.params });
|
|
107765
|
+
runs.push({
|
|
107766
|
+
commentId: request.commentId,
|
|
107767
|
+
account: request.account,
|
|
107768
|
+
outcome: result.outcome,
|
|
107769
|
+
..."reason" in result ? { reason: redactReason(result.reason, mapped.params) } : {}
|
|
107770
|
+
});
|
|
107771
|
+
} catch (err) {
|
|
107772
|
+
runs.push({ commentId: request.commentId, account: request.account, outcome: "error", reason: redactReason(err instanceof Error ? err.message : String(err), mapped.params) });
|
|
107773
|
+
}
|
|
107774
|
+
}
|
|
107775
|
+
return { from: { journey: opts.from, outcome: "ok", records: count }, runs, unmatched };
|
|
107776
|
+
}
|
|
107777
|
+
|
|
107778
|
+
// src/journey-cli/chain.ts
|
|
107779
|
+
function registerJourneyChain(journey, program2, deps) {
|
|
107780
|
+
withReplayAllowFlag(withEnvironmentFlags(withBrowserLaunchFlags(withEmulationFlags(journey.command("chain"))))).requiredOption("--from <id>", "the discover Journey, run once to produce the records").requiredOption("--to <id>", "the prepare-only reply Journey, run once per matched request").requiredOption("--requests <file>", "JSON Lines file of approved requests ({commentId, account, replyText})").option("--dir <path>", "journeys directory (default: the repo's .jevitate/journeys; outside a repo ~/.jevitate/journeys)").option("--storage-state <file>", "Playwright storageState JSON to start each run authenticated; must exist").option("--allow-draft", "also run Journeys that are not promoted (authoring); without it both must be promoted").option("--json", "emit a JSON envelope").action(async function() {
|
|
107781
|
+
const { from, to, requests: requestsFile, dir, storageState: storageStateFlag, json: json2, allowDraft } = this.opts();
|
|
107782
|
+
const { env: envName, baseUrl } = this.opts();
|
|
107783
|
+
let environment;
|
|
107784
|
+
let allow;
|
|
107785
|
+
try {
|
|
107786
|
+
allow = replayAllowFromFlags(this.opts().allow);
|
|
107787
|
+
environment = environmentFromFlags(
|
|
107788
|
+
{ ...envName === void 0 ? {} : { env: envName }, ...baseUrl === void 0 ? {} : { baseUrl } },
|
|
107789
|
+
environmentSeams(deps)
|
|
107790
|
+
);
|
|
107791
|
+
} catch (err) {
|
|
107792
|
+
if (!isEnvironmentError(err)) throw err;
|
|
107793
|
+
emitJson(program2, fail(err.code, err.message));
|
|
107794
|
+
return;
|
|
107795
|
+
}
|
|
107796
|
+
const storageState = storageStateFlag ?? environment?.storageState;
|
|
107797
|
+
if (storageState !== void 0 && !existsSync27(storageState)) {
|
|
107798
|
+
emitJson(program2, fail("E_CHAIN_ARGS", `storage state not found: ${storageState}`));
|
|
107799
|
+
return;
|
|
107800
|
+
}
|
|
107801
|
+
let requests;
|
|
107802
|
+
try {
|
|
107803
|
+
requests = readFileSync33(requestsFile, "utf8");
|
|
107804
|
+
} catch (err) {
|
|
107805
|
+
emitJson(program2, fail("E_CHAIN_ARGS", `could not read requests file ${requestsFile}: ${err instanceof Error ? err.message : String(err)}`));
|
|
107806
|
+
return;
|
|
107807
|
+
}
|
|
107808
|
+
let browser;
|
|
107809
|
+
try {
|
|
107810
|
+
browser = browserRunFromFlags(this.opts(), deps.explore?.env ?? process.env);
|
|
107811
|
+
} catch (err) {
|
|
107812
|
+
emitJson(program2, fail("E_CHAIN_ARGS", err instanceof Error ? err.message : String(err)));
|
|
107813
|
+
return;
|
|
107814
|
+
}
|
|
107815
|
+
let emulation;
|
|
107816
|
+
try {
|
|
107817
|
+
emulation = emulationFromFlags(this.opts());
|
|
107818
|
+
} catch (err) {
|
|
107819
|
+
emitJson(program2, fail("E_CHAIN_ARGS", err instanceof Error ? err.message : String(err)));
|
|
107820
|
+
return;
|
|
107821
|
+
}
|
|
107822
|
+
try {
|
|
107823
|
+
const result = await withSiteGate(
|
|
107824
|
+
resolveDbPath(deps),
|
|
107825
|
+
(siteGate) => runJourneyChain({
|
|
107826
|
+
from,
|
|
107827
|
+
to,
|
|
107828
|
+
requests,
|
|
107829
|
+
dir: resolveJourneysDir(deps, dir),
|
|
107830
|
+
requirePromoted: allowDraft !== true,
|
|
107831
|
+
...siteGate === void 0 ? {} : { siteGate },
|
|
107832
|
+
browserPortFactory: deps.explore?.browserPortFactory,
|
|
107833
|
+
...browser === void 0 ? {} : { browser },
|
|
107834
|
+
...emulation === void 0 ? {} : { emulation },
|
|
107835
|
+
...storageState !== void 0 ? { storageState } : {},
|
|
107836
|
+
...environment === void 0 ? {} : { environment },
|
|
107837
|
+
...allow.length === 0 ? {} : { allow }
|
|
107838
|
+
})
|
|
107839
|
+
);
|
|
107840
|
+
const envelope = ok(result);
|
|
107841
|
+
if (json2) emitJson(program2, envelope);
|
|
107842
|
+
else writeRawResult(program2, result);
|
|
107843
|
+
process.exitCode = chainSucceeded(result) ? 0 : 1;
|
|
107844
|
+
} catch (err) {
|
|
107845
|
+
if (err instanceof JourneyChainError) {
|
|
107846
|
+
emitJson(program2, fail(err.code, err.message));
|
|
107847
|
+
} else if (err instanceof UnknownJourneyError) {
|
|
107848
|
+
emitJson(program2, fail("E_UNKNOWN_JOURNEY", String(err.message)));
|
|
107849
|
+
} else if (isEnvironmentError(err)) {
|
|
107850
|
+
emitJson(program2, fail(err.code, err.message));
|
|
107851
|
+
} else {
|
|
107852
|
+
emitJson(program2, fail("E_CHAIN", String(err instanceof Error ? err.message : err)));
|
|
107853
|
+
}
|
|
107854
|
+
}
|
|
107855
|
+
});
|
|
107856
|
+
}
|
|
107857
|
+
|
|
107507
107858
|
// src/journey-cli/promote.ts
|
|
107508
107859
|
import { readFile as readFile31 } from "node:fs/promises";
|
|
107509
107860
|
|
|
@@ -108052,7 +108403,7 @@ function registerJourneyReview(journey, program2, deps) {
|
|
|
108052
108403
|
}
|
|
108053
108404
|
|
|
108054
108405
|
// src/journey-cli/migrate.ts
|
|
108055
|
-
import { existsSync as
|
|
108406
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
108056
108407
|
|
|
108057
108408
|
// src/journey-migrate-api.ts
|
|
108058
108409
|
import { readdir as readdir11, readFile as readFile32, writeFile as writeFile37 } from "node:fs/promises";
|
|
@@ -108308,7 +108659,7 @@ function registerJourneyMigrate(journey, program2, deps) {
|
|
|
108308
108659
|
return;
|
|
108309
108660
|
}
|
|
108310
108661
|
const storageState = storageStateFlag ?? environment?.storageState;
|
|
108311
|
-
if (storageState !== void 0 && !
|
|
108662
|
+
if (storageState !== void 0 && !existsSync28(storageState)) {
|
|
108312
108663
|
emitJson(program2, fail("E_JOURNEY_MIGRATE_ARGS", `storage state not found: ${storageState}`));
|
|
108313
108664
|
return;
|
|
108314
108665
|
}
|
|
@@ -108641,7 +108992,7 @@ function registerJourneyLint(journey, program2, deps) {
|
|
|
108641
108992
|
}
|
|
108642
108993
|
|
|
108643
108994
|
// src/journey-cli/verify.ts
|
|
108644
|
-
import { existsSync as
|
|
108995
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
108645
108996
|
|
|
108646
108997
|
// src/journey-verify.ts
|
|
108647
108998
|
function verifyExitCode(verdict) {
|
|
@@ -108691,10 +109042,14 @@ async function verifyJourneyMutations(opts, run = runJourneyProgrammatically) {
|
|
|
108691
109042
|
structuredFailures: true,
|
|
108692
109043
|
...how.journey === journey ? {} : { mutateJourney: (j) => describe6(j, m, replayOpts2).journey },
|
|
108693
109044
|
...how.skipIndex === void 0 ? {} : { skipStep: (i) => i === how.skipIndex },
|
|
109045
|
+
...how.swapSelectAtStep === void 0 ? {} : { selectAlternativeAtStep: how.swapSelectAtStep },
|
|
108694
109046
|
...how.blockIndex === void 0 ? {} : { blockWritesAtStep: how.blockIndex }
|
|
108695
109047
|
});
|
|
108696
109048
|
const blocked = r.blockedWrites ?? [];
|
|
108697
109049
|
const blockedFields = how.blockIndex === void 0 ? {} : { blockedWrites: blocked.map((b2) => `${b2.method} ${b2.path}`) };
|
|
109050
|
+
if (r.outcome === "quarantined" && /no-alternative/.test(r.reason)) {
|
|
109051
|
+
return { outcome: "not-applied", failedSites: [], ...blockedFields, reason: r.reason };
|
|
109052
|
+
}
|
|
108698
109053
|
if (how.blockIndex !== void 0 && !blockedOwnWrite(how.blockRequests ?? [], blocked)) {
|
|
108699
109054
|
return {
|
|
108700
109055
|
outcome: "not-applied",
|
|
@@ -108716,7 +109071,15 @@ async function verifyJourneyMutations(opts, run = runJourneyProgrammatically) {
|
|
|
108716
109071
|
for (const m of plan2.mutations) {
|
|
108717
109072
|
const first = await replay(m, mutationReplay);
|
|
108718
109073
|
const relaxed2 = needsRelaxedReplay(plan2, m, first) ? await replay(m, relaxedMutationReplay) : void 0;
|
|
108719
|
-
mutations.push({
|
|
109074
|
+
mutations.push({
|
|
109075
|
+
kind: m.kind,
|
|
109076
|
+
step: m.step,
|
|
109077
|
+
id: m.id,
|
|
109078
|
+
...m.param === void 0 ? {} : { param: m.param },
|
|
109079
|
+
...m.source === void 0 ? {} : { source: m.source },
|
|
109080
|
+
...first,
|
|
109081
|
+
...relaxed2 === void 0 ? {} : { relaxed: relaxed2 }
|
|
109082
|
+
});
|
|
108720
109083
|
}
|
|
108721
109084
|
}
|
|
108722
109085
|
const results = new Map(
|
|
@@ -108784,7 +109147,7 @@ function registerJourneyVerify(journey, program2, deps) {
|
|
|
108784
109147
|
...ownFixtureFlags.after === void 0 && environment?.hooks?.after !== void 0 ? { after: environment.hooks.after } : {}
|
|
108785
109148
|
};
|
|
108786
109149
|
const storageState = storageStateFlag ?? environment?.storageState;
|
|
108787
|
-
if (storageState !== void 0 && !
|
|
109150
|
+
if (storageState !== void 0 && !existsSync29(storageState)) {
|
|
108788
109151
|
emitJson(program2, fail("E_JOURNEY_VERIFY_ARGS", `storage state not found: ${storageState}`));
|
|
108789
109152
|
return;
|
|
108790
109153
|
}
|
|
@@ -109211,7 +109574,7 @@ function registerJourneyLinkCommand(journey, program2, deps) {
|
|
|
109211
109574
|
}
|
|
109212
109575
|
|
|
109213
109576
|
// src/journey-annotate-cli.ts
|
|
109214
|
-
import { existsSync as
|
|
109577
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
109215
109578
|
function registerJourneyAnnotateCommand(journey, program2, deps) {
|
|
109216
109579
|
withScreenshotsFlag(withEnvironmentFlags(withBrowserLaunchFlags(withEmulationFlags(withFixtureFlags(journey.command("annotate <id>")))))).description(
|
|
109217
109580
|
"draft each step's objective/expected result (and the goal/success criteria when missing) by replaying the Journey; writes a reviewable draft, never the Journey \u2014 `--approve` applies a reviewed draft (human gate)"
|
|
@@ -109260,7 +109623,7 @@ function registerJourneyAnnotateCommand(journey, program2, deps) {
|
|
|
109260
109623
|
...ownFixtureFlags.after === void 0 && environment?.hooks?.after !== void 0 ? { after: environment.hooks.after } : {}
|
|
109261
109624
|
};
|
|
109262
109625
|
const storageState = storageStateFlag ?? environment?.storageState;
|
|
109263
|
-
if (storageState !== void 0 && !
|
|
109626
|
+
if (storageState !== void 0 && !existsSync30(storageState)) {
|
|
109264
109627
|
emitJson(program2, fail("E_JOURNEY_ANNOTATE_ARGS", `storage state not found: ${storageState}`));
|
|
109265
109628
|
return;
|
|
109266
109629
|
}
|
|
@@ -109348,7 +109711,7 @@ review or edit it, then apply it: jevitate journey annotate ${id} --approve
|
|
|
109348
109711
|
}
|
|
109349
109712
|
|
|
109350
109713
|
// src/journey-demo-cli.ts
|
|
109351
|
-
import { existsSync as
|
|
109714
|
+
import { existsSync as existsSync31 } from "node:fs";
|
|
109352
109715
|
import { join as join64, resolve as resolvePath15 } from "node:path";
|
|
109353
109716
|
function registerJourneyDemoCommand(journey, program2, deps) {
|
|
109354
109717
|
withScreenshotsFlag(withEnvironmentFlags(withDemoFlags(withBrowserLaunchFlags(withEmulationFlags(withFixtureFlags(journey.command("demo <id>"))))))).description(
|
|
@@ -109372,7 +109735,7 @@ function registerJourneyDemoCommand(journey, program2, deps) {
|
|
|
109372
109735
|
...ownFixtureFlags.after === void 0 && environment?.hooks?.after !== void 0 ? { after: environment.hooks.after } : {}
|
|
109373
109736
|
};
|
|
109374
109737
|
const storageState = storageStateFlag ?? environment?.storageState;
|
|
109375
|
-
if (storageState !== void 0 && !
|
|
109738
|
+
if (storageState !== void 0 && !existsSync31(storageState)) {
|
|
109376
109739
|
emitJson(program2, fail("E_JOURNEY_DEMO_ARGS", `storage state not found: ${storageState}`));
|
|
109377
109740
|
return;
|
|
109378
109741
|
}
|
|
@@ -109468,6 +109831,7 @@ function registerJourneyCommands(program2, deps) {
|
|
|
109468
109831
|
registerJourneyList(journey, program2, deps);
|
|
109469
109832
|
registerJourneyFind(journey, program2, deps);
|
|
109470
109833
|
registerJourneyRun(journey, program2, deps);
|
|
109834
|
+
registerJourneyChain(journey, program2, deps);
|
|
109471
109835
|
registerJourneyPromote(journey, program2, deps);
|
|
109472
109836
|
registerJourneyReview(journey, program2, deps);
|
|
109473
109837
|
registerJourneyMigrate(journey, program2, deps);
|
|
@@ -109492,7 +109856,7 @@ function registerBuiltinAnalyzers() {
|
|
|
109492
109856
|
}
|
|
109493
109857
|
|
|
109494
109858
|
// src/source-cli.ts
|
|
109495
|
-
import { existsSync as
|
|
109859
|
+
import { existsSync as existsSync32 } from "node:fs";
|
|
109496
109860
|
|
|
109497
109861
|
// src/source-run-api.ts
|
|
109498
109862
|
var realResolvedJourneyRunner = async (file2, params, policy, storageState, emulation, browser, siteGate) => {
|
|
@@ -109710,7 +110074,7 @@ function registerSourceCommands(program2, deps) {
|
|
|
109710
110074
|
"Playwright storageState JSON to start the session authenticated (#118: required when the journey declares metadata.requiresAuth); must exist"
|
|
109711
110075
|
).option("--json", "emit a JSON envelope").option(TAG_FLAG, TAG_HELP, collectTag, []).action(taggedAction(program2, "source run", async function(name, journeyId) {
|
|
109712
110076
|
const { param, storageState, json: json2, ...emulationFlags } = this.opts();
|
|
109713
|
-
if (storageState !== void 0 && !
|
|
110077
|
+
if (storageState !== void 0 && !existsSync32(storageState)) {
|
|
109714
110078
|
emitJson(program2, fail("E_SOURCE_RUN_ARGS", `storage state not found: ${storageState}`));
|
|
109715
110079
|
return;
|
|
109716
110080
|
}
|
|
@@ -109773,7 +110137,7 @@ function registerSourceCommands(program2, deps) {
|
|
|
109773
110137
|
}
|
|
109774
110138
|
|
|
109775
110139
|
// src/load-cli.ts
|
|
109776
|
-
import { existsSync as
|
|
110140
|
+
import { existsSync as existsSync33 } from "node:fs";
|
|
109777
110141
|
|
|
109778
110142
|
// ../load/dist/percentiles.js
|
|
109779
110143
|
function percentile(sorted2, p) {
|
|
@@ -109981,7 +110345,7 @@ function registerLoadCommands(program2, deps) {
|
|
|
109981
110345
|
return;
|
|
109982
110346
|
}
|
|
109983
110347
|
const storageState = storageStateFlag ?? environment?.storageState;
|
|
109984
|
-
if (storageState !== void 0 && !
|
|
110348
|
+
if (storageState !== void 0 && !existsSync33(storageState)) {
|
|
109985
110349
|
emitJson(program2, fail("E_LOAD_RUN_ARGS", `storage state not found: ${storageState}`));
|
|
109986
110350
|
return;
|
|
109987
110351
|
}
|
|
@@ -110031,10 +110395,10 @@ function registerLoadCommands(program2, deps) {
|
|
|
110031
110395
|
}
|
|
110032
110396
|
|
|
110033
110397
|
// src/explore-cli/run.ts
|
|
110034
|
-
import { existsSync as
|
|
110398
|
+
import { existsSync as existsSync35 } from "node:fs";
|
|
110035
110399
|
|
|
110036
110400
|
// src/type-fixture-file.ts
|
|
110037
|
-
import { readFileSync as
|
|
110401
|
+
import { readFileSync as readFileSync34, statSync as statSync10 } from "node:fs";
|
|
110038
110402
|
import { basename as basename15, resolve as resolve18 } from "node:path";
|
|
110039
110403
|
var TYPE_FIXTURE_MAX_BYTES = 256 * 1024;
|
|
110040
110404
|
function loadTypeFixtures(specs, cwd = process.cwd()) {
|
|
@@ -110053,7 +110417,7 @@ function loadTypeFixtures(specs, cwd = process.cwd()) {
|
|
|
110053
110417
|
if (size > TYPE_FIXTURE_MAX_BYTES) {
|
|
110054
110418
|
throw new TypeFixtureSpecError(`--type-fixture ${descriptor}: ${path2} is ${size} bytes (at most ${TYPE_FIXTURE_MAX_BYTES})`);
|
|
110055
110419
|
}
|
|
110056
|
-
const bytes =
|
|
110420
|
+
const bytes = readFileSync34(abs);
|
|
110057
110421
|
let text2;
|
|
110058
110422
|
try {
|
|
110059
110423
|
text2 = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
@@ -110374,7 +110738,7 @@ async function runExploreMultiRun(args) {
|
|
|
110374
110738
|
import { resolve as resolvePath16 } from "node:path";
|
|
110375
110739
|
|
|
110376
110740
|
// src/campaign-api.ts
|
|
110377
|
-
import { existsSync as
|
|
110741
|
+
import { existsSync as existsSync34, readFileSync as readFileSync35 } from "node:fs";
|
|
110378
110742
|
import { mkdir as mkdir31, writeFile as writeFile39 } from "node:fs/promises";
|
|
110379
110743
|
import { homedir as homedir5 } from "node:os";
|
|
110380
110744
|
import { dirname as dirname28, isAbsolute as isAbsolute11, join as join66, resolve as resolve19 } from "node:path";
|
|
@@ -110491,7 +110855,7 @@ var at2 = (path2) => path2.length === 0 ? "spec" : path2.map((p) => typeof p ===
|
|
|
110491
110855
|
async function validateCampaign(specPath, opts) {
|
|
110492
110856
|
let raw;
|
|
110493
110857
|
try {
|
|
110494
|
-
raw = JSON.parse(
|
|
110858
|
+
raw = JSON.parse(readFileSync35(specPath, "utf8"));
|
|
110495
110859
|
} catch (e) {
|
|
110496
110860
|
throw new CampaignSpecError([`cannot read ${specPath}: ${e instanceof SyntaxError ? "not valid JSON" : e instanceof Error ? e.message : String(e)}`]);
|
|
110497
110861
|
}
|
|
@@ -110515,8 +110879,8 @@ async function validateCampaignSpec(raw, specPath, opts) {
|
|
|
110515
110879
|
problems.push(`env: ${err.message}`);
|
|
110516
110880
|
}
|
|
110517
110881
|
const defaultSession = spec.storageState === void 0 ? environment?.storageState : abs(spec.storageState);
|
|
110518
|
-
if (spec.storageState !== void 0 && !
|
|
110519
|
-
if (spec.fixtures !== void 0 && !
|
|
110882
|
+
if (spec.storageState !== void 0 && !existsSync34(abs(spec.storageState))) problems.push(`storageState: not found: ${abs(spec.storageState)}`);
|
|
110883
|
+
if (spec.fixtures !== void 0 && !existsSync34(abs(spec.fixtures))) problems.push(`fixtures: not found: ${abs(spec.fixtures)}`);
|
|
110520
110884
|
if ((spec.before !== void 0 || spec.after !== void 0) && opts.allowShellHooks !== true) {
|
|
110521
110885
|
problems.push("before/after: operator shell hooks run only with --allow-shell-hooks");
|
|
110522
110886
|
}
|
|
@@ -110541,7 +110905,7 @@ async function validateCampaignSpec(raw, specPath, opts) {
|
|
|
110541
110905
|
}
|
|
110542
110906
|
if (new Set(job.strategies).size !== job.strategies.length) problems.push(`${where}.strategies: duplicate strategy`);
|
|
110543
110907
|
const session2 = job.storageState === void 0 ? defaultSession : abs(job.storageState);
|
|
110544
|
-
if (job.storageState !== void 0 && !
|
|
110908
|
+
if (job.storageState !== void 0 && !existsSync34(abs(job.storageState))) problems.push(`${where}.storageState: not found: ${abs(job.storageState)}`);
|
|
110545
110909
|
let stored = null;
|
|
110546
110910
|
try {
|
|
110547
110911
|
stored = await registry3.get(job.journey);
|
|
@@ -112309,7 +112673,7 @@ function registerExploreRun(program2, deps, buildProgram2) {
|
|
|
112309
112673
|
emitExplore(fail(err.code, err.message));
|
|
112310
112674
|
return;
|
|
112311
112675
|
}
|
|
112312
|
-
if (o.storageState !== void 0 && !
|
|
112676
|
+
if (o.storageState !== void 0 && !existsSync35(o.storageState) && (authCheck.mode === "off" || projectPersona?.login === void 0)) {
|
|
112313
112677
|
emitExplore(fail("E_EXPLORE_ARGS", `storage state not found: ${o.storageState}`));
|
|
112314
112678
|
return;
|
|
112315
112679
|
}
|
|
@@ -112601,11 +112965,11 @@ function pick3(k, v) {
|
|
|
112601
112965
|
import { resolve as resolve22 } from "node:path";
|
|
112602
112966
|
|
|
112603
112967
|
// src/sweep-api.ts
|
|
112604
|
-
import { existsSync as
|
|
112968
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync11, readFileSync as readFileSync36, realpathSync as realpathSync5, statSync as statSync11, writeFileSync as writeFileSync13 } from "node:fs";
|
|
112605
112969
|
import { basename as basename18, dirname as dirname30, extname as extname2, join as join68, resolve as resolve21 } from "node:path";
|
|
112606
112970
|
|
|
112607
112971
|
// src/mcp-paths.ts
|
|
112608
|
-
import { existsSync as
|
|
112972
|
+
import { existsSync as existsSync36, realpathSync as realpathSync4 } from "node:fs";
|
|
112609
112973
|
import { basename as basename17, dirname as dirname29, isAbsolute as isAbsolute12, join as join67, relative as relative9, resolve as resolve20, sep as sep9 } from "node:path";
|
|
112610
112974
|
var McpPathError = class extends Error {
|
|
112611
112975
|
error = "invalid_args";
|
|
@@ -112623,7 +112987,7 @@ function realish(p) {
|
|
|
112623
112987
|
let head2 = p;
|
|
112624
112988
|
const tail = [];
|
|
112625
112989
|
for (; ; ) {
|
|
112626
|
-
if (
|
|
112990
|
+
if (existsSync36(head2)) {
|
|
112627
112991
|
try {
|
|
112628
112992
|
return join67(realpathSync4(head2), ...tail);
|
|
112629
112993
|
} catch {
|
|
@@ -112999,6 +113363,29 @@ var CLI_TOOL_SPECS = [
|
|
|
112999
113363
|
omitted: { "--dir": OMIT.storeDir, "--allow": OMIT.mcpOrigins, ...HOOK_FLAGS, ...BROWSER_FLAGS, ...JSON_FLAG }
|
|
113000
113364
|
}
|
|
113001
113365
|
},
|
|
113366
|
+
{
|
|
113367
|
+
name: "chain_journeys",
|
|
113368
|
+
description: "`jevitate journey chain --from <discover> --to <reply> --requests <file>` (#580): run a discover Journey once, then a prepare-only reply Journey once per approved request in the JSON Lines file ({commentId, account, replyText}) matched to a discovered record by commentId AND account. Both Journeys must be promoted. Unmatched requests never run; an empty discovery stops the chain (no target is guessed). The result names ids and outcomes only, never record or reply text. Exit 0 only when every request matched and its run was ok.",
|
|
113369
|
+
command: {
|
|
113370
|
+
path: "journey chain",
|
|
113371
|
+
params: {
|
|
113372
|
+
from: s2("--from", { required: true }),
|
|
113373
|
+
to: s2("--to", { required: true }),
|
|
113374
|
+
requests: path("--requests", { required: true }),
|
|
113375
|
+
storageState: session("--storage-state"),
|
|
113376
|
+
...EXTENSION,
|
|
113377
|
+
...EMULATION,
|
|
113378
|
+
...ENVIRONMENT
|
|
113379
|
+
},
|
|
113380
|
+
omitted: {
|
|
113381
|
+
"--allow-draft": "#580: over MCP a chain runs promoted Journeys only, as run_journey does; running drafts is the operator's CLI call",
|
|
113382
|
+
"--dir": OMIT.storeDir,
|
|
113383
|
+
"--allow": OMIT.mcpOrigins,
|
|
113384
|
+
...BROWSER_FLAGS,
|
|
113385
|
+
...JSON_FLAG
|
|
113386
|
+
}
|
|
113387
|
+
}
|
|
113388
|
+
},
|
|
113002
113389
|
{
|
|
113003
113390
|
name: "publish_journey",
|
|
113004
113391
|
description: "`jevitate journey publish <id> --to <source>`: publish a promoted Journey into a registered source on a new publish/<id> branch (a PR when gh is available). Secret references only; declared origins must cover its steps.",
|
|
@@ -114025,7 +114412,7 @@ function personaOf(value, base, roots, where, problems) {
|
|
|
114025
114412
|
}
|
|
114026
114413
|
try {
|
|
114027
114414
|
const confined = confineMcpPath(abs, `persona of ${where}`, roots, { session: true });
|
|
114028
|
-
if (!
|
|
114415
|
+
if (!existsSync37(confined)) {
|
|
114029
114416
|
problems.push(`${where}: persona storage state not found: ${confined}`);
|
|
114030
114417
|
return void 0;
|
|
114031
114418
|
}
|
|
@@ -114094,8 +114481,8 @@ function validateRunShaping(options, strategy, where, problems) {
|
|
|
114094
114481
|
}
|
|
114095
114482
|
function loadSweepTargets(path2, opts = {}) {
|
|
114096
114483
|
const abs = resolve21(path2);
|
|
114097
|
-
if (!
|
|
114098
|
-
const text2 =
|
|
114484
|
+
if (!existsSync37(abs)) throw new SweepSpecError(`targets file not found: ${abs}`);
|
|
114485
|
+
const text2 = readFileSync36(abs, "utf8");
|
|
114099
114486
|
const isTsv = /\.(tsv|txt)$/i.test(abs);
|
|
114100
114487
|
const parsed = isTsv ? parseTsv(text2, path2) : parseJson(text2, path2);
|
|
114101
114488
|
const problems = [...parsed.problems];
|
|
@@ -114342,9 +114729,9 @@ function targetArgv(plan2, target, runDir) {
|
|
|
114342
114729
|
];
|
|
114343
114730
|
}
|
|
114344
114731
|
function finishedEnvelope(envelopePath) {
|
|
114345
|
-
if (!
|
|
114732
|
+
if (!existsSync37(envelopePath)) return void 0;
|
|
114346
114733
|
try {
|
|
114347
|
-
const env = JSON.parse(
|
|
114734
|
+
const env = JSON.parse(readFileSync36(envelopePath, "utf8"));
|
|
114348
114735
|
if (!isRecord(env) || env.ok !== true || !isRecord(env.data)) return void 0;
|
|
114349
114736
|
if (env.data.interrupted !== void 0) return void 0;
|
|
114350
114737
|
return env;
|
|
@@ -114718,7 +115105,7 @@ function registerVerifyFixCommands(program2, deps) {
|
|
|
114718
115105
|
}
|
|
114719
115106
|
|
|
114720
115107
|
// src/author-journey-cli.ts
|
|
114721
|
-
import { existsSync as
|
|
115108
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
114722
115109
|
var AUTHOR_GOAL_RUN_FLAGS = [
|
|
114723
115110
|
"successWhen",
|
|
114724
115111
|
"allowVacuousChecks",
|
|
@@ -114814,7 +115201,7 @@ function registerAuthorJourneyCommands(program2, deps) {
|
|
|
114814
115201
|
].join("\n")
|
|
114815
115202
|
).action(async function() {
|
|
114816
115203
|
const o = this.opts();
|
|
114817
|
-
if (o.storageState !== void 0 && !
|
|
115204
|
+
if (o.storageState !== void 0 && !existsSync38(o.storageState)) {
|
|
114818
115205
|
emitJson(program2, fail("E_EXPLORE_ARGS", `storage state not found: ${o.storageState}`));
|
|
114819
115206
|
return;
|
|
114820
115207
|
}
|
|
@@ -114936,11 +115323,11 @@ function registerAuthorJourneyCommands(program2, deps) {
|
|
|
114936
115323
|
}
|
|
114937
115324
|
|
|
114938
115325
|
// src/demo-aspect-cli.ts
|
|
114939
|
-
import { existsSync as
|
|
115326
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
114940
115327
|
import { join as join71, resolve as resolvePath18 } from "node:path";
|
|
114941
115328
|
|
|
114942
115329
|
// src/demo-aspect-api.ts
|
|
114943
|
-
import { existsSync as
|
|
115330
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
114944
115331
|
import { mkdir as mkdir33, mkdtemp as mkdtemp5, readFile as readFile33, rm as rm13, writeFile as writeFile41 } from "node:fs/promises";
|
|
114945
115332
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
114946
115333
|
import { dirname as dirname31, join as join70 } from "node:path";
|
|
@@ -115277,7 +115664,7 @@ async function demoAspect(opts) {
|
|
|
115277
115664
|
const store = new FsJourneyStore(opts.journeysDir);
|
|
115278
115665
|
if (await store.get(id) !== null) throw new DemoExistsError(`journey '${id}' already exists \u2014 pick another --id (nothing was changed)`);
|
|
115279
115666
|
const recordPath = demoDraftPath(opts.journeysDir, id);
|
|
115280
|
-
if (
|
|
115667
|
+
if (existsSync39(recordPath)) {
|
|
115281
115668
|
throw new DemoExistsError(`a demo draft '${id}' is waiting for approval (${recordPath}) \u2014 approve it with \`jevitate demo approve ${id}\`, or pick another --id`);
|
|
115282
115669
|
}
|
|
115283
115670
|
const maxReplays = opts.maxReplays ?? DEMO_MINIMIZE_MAX_REPLAYS;
|
|
@@ -115524,7 +115911,7 @@ function replayOptionsFrom(cmd, deps, o, environment) {
|
|
|
115524
115911
|
fixtureIdentity: o.fixtureIdentity
|
|
115525
115912
|
};
|
|
115526
115913
|
const storageState = o.storageState ?? environment.storageState;
|
|
115527
|
-
if (storageState !== void 0 && !
|
|
115914
|
+
if (storageState !== void 0 && !existsSync40(storageState)) throw new DemoAspectArgsError(`storage state not found: ${storageState}`);
|
|
115528
115915
|
let browser;
|
|
115529
115916
|
let emulation;
|
|
115530
115917
|
try {
|
|
@@ -115877,12 +116264,12 @@ function registerRecordCommands(program2, deps) {
|
|
|
115877
116264
|
}
|
|
115878
116265
|
|
|
115879
116266
|
// src/regression-cli.ts
|
|
115880
|
-
import { existsSync as
|
|
116267
|
+
import { existsSync as existsSync42 } from "node:fs";
|
|
115881
116268
|
import { readFile as readFile35, writeFile as writeFile43 } from "node:fs/promises";
|
|
115882
116269
|
import { join as join73 } from "node:path";
|
|
115883
116270
|
|
|
115884
116271
|
// src/regression-api.ts
|
|
115885
|
-
import { existsSync as
|
|
116272
|
+
import { existsSync as existsSync41 } from "node:fs";
|
|
115886
116273
|
import { readFile as readFile34 } from "node:fs/promises";
|
|
115887
116274
|
var RegressionExistsError = class extends Error {
|
|
115888
116275
|
code = "E_REGRESSION_EXISTS";
|
|
@@ -115970,7 +116357,7 @@ function describeNoOracle(missionResult) {
|
|
|
115970
116357
|
}
|
|
115971
116358
|
async function runRegressionCapture(opts) {
|
|
115972
116359
|
const recordingPath = safeChildPath(opts.regressionsDir, opts.id, { what: "regression id", suffix: ".recording.json" });
|
|
115973
|
-
if (opts.force !== true &&
|
|
116360
|
+
if (opts.force !== true && existsSync41(recordingPath)) {
|
|
115974
116361
|
throw new RegressionExistsError(opts.id, opts.regressionsDir);
|
|
115975
116362
|
}
|
|
115976
116363
|
const raw = JSON.parse(await readFile34(opts.failingRecordingPath, "utf8"));
|
|
@@ -116212,12 +116599,12 @@ function registerRegressionCommands(program2, deps) {
|
|
|
116212
116599
|
const { from, id, dir, attempts, summary: summary2, result: resultPath, fingerprint: fingerprint2, storageState, force, json: json2, param } = flags;
|
|
116213
116600
|
if (refuseUnsafeName(program2, id, "regression id")) return;
|
|
116214
116601
|
for (const [flag, path2] of [["--from", from], ["--result", resultPath]]) {
|
|
116215
|
-
if (path2 !== void 0 && !
|
|
116602
|
+
if (path2 !== void 0 && !existsSync42(path2)) {
|
|
116216
116603
|
emitJson(program2, fail("E_REGRESSION_ARGS", `${flag} file not found: ${path2}`));
|
|
116217
116604
|
return;
|
|
116218
116605
|
}
|
|
116219
116606
|
}
|
|
116220
|
-
if (storageState !== void 0 && !
|
|
116607
|
+
if (storageState !== void 0 && !existsSync42(storageState)) {
|
|
116221
116608
|
emitJson(program2, fail("E_REGRESSION_ARGS", `storage state not found: ${storageState}`));
|
|
116222
116609
|
return;
|
|
116223
116610
|
}
|
|
@@ -116314,7 +116701,7 @@ function registerRegressionCommands(program2, deps) {
|
|
|
116314
116701
|
return;
|
|
116315
116702
|
}
|
|
116316
116703
|
const storageState = storageStateFlag ?? environment?.storageState;
|
|
116317
|
-
if (storageState !== void 0 && !
|
|
116704
|
+
if (storageState !== void 0 && !existsSync42(storageState)) {
|
|
116318
116705
|
emitJson(program2, fail("E_REGRESSION_ARGS", `storage state not found: ${storageState}`));
|
|
116319
116706
|
return;
|
|
116320
116707
|
}
|
|
@@ -116327,7 +116714,7 @@ function registerRegressionCommands(program2, deps) {
|
|
|
116327
116714
|
}
|
|
116328
116715
|
if (refuseUnsafeName(program2, id, "regression id")) return;
|
|
116329
116716
|
const regressionsDir = resolveRegressionsDir(dir);
|
|
116330
|
-
if (!
|
|
116717
|
+
if (!existsSync42(join73(regressionsDir, `${id}.recording.json`))) {
|
|
116331
116718
|
const notFound = new RegressionNotFoundError(id, regressionsDir);
|
|
116332
116719
|
emitJson(program2, fail(notFound.code, notFound.message));
|
|
116333
116720
|
return;
|
|
@@ -116385,7 +116772,7 @@ function registerRegressionCommands(program2, deps) {
|
|
|
116385
116772
|
}
|
|
116386
116773
|
|
|
116387
116774
|
// src/mission-api.ts
|
|
116388
|
-
import { existsSync as
|
|
116775
|
+
import { existsSync as existsSync43 } from "node:fs";
|
|
116389
116776
|
import { resolve as resolvePath19 } from "node:path";
|
|
116390
116777
|
var UnknownMissionTargetError = class extends Error {
|
|
116391
116778
|
};
|
|
@@ -116423,7 +116810,7 @@ function applyAuth(target, auth) {
|
|
|
116423
116810
|
}
|
|
116424
116811
|
if (auth.storageState !== void 0) {
|
|
116425
116812
|
const abs = resolvePath19(auth.storageState);
|
|
116426
|
-
if (!
|
|
116813
|
+
if (!existsSync43(abs)) throw new MissionTargetAuthError(`storage state not found: ${abs}`);
|
|
116427
116814
|
base.storageState = abs;
|
|
116428
116815
|
}
|
|
116429
116816
|
if (auth.saveStorageState !== void 0) base.saveStorageState = auth.saveStorageState === true ? true : resolvePath19(auth.saveStorageState);
|
|
@@ -116468,7 +116855,7 @@ async function promoteMissionTarget(ctx, id) {
|
|
|
116468
116855
|
}
|
|
116469
116856
|
|
|
116470
116857
|
// src/mission-queue-cli.ts
|
|
116471
|
-
import { readFileSync as
|
|
116858
|
+
import { readFileSync as readFileSync37 } from "node:fs";
|
|
116472
116859
|
import { Option as Option2 } from "commander";
|
|
116473
116860
|
|
|
116474
116861
|
// src/mcp-api.ts
|
|
@@ -116527,6 +116914,9 @@ var ALLOWED_TOOLS = [
|
|
|
116527
116914
|
// #401 — the assertion-strength lint promote_journey applies; #402 — its mutation proof.
|
|
116528
116915
|
"lint_journey",
|
|
116529
116916
|
"verify_journey",
|
|
116917
|
+
// #580 — the two-journey chain: discover once, prepare-only reply per approved request. Promoted
|
|
116918
|
+
// Journeys only (--allow-draft is CLI-only); ids and outcomes only, never record or reply text.
|
|
116919
|
+
"chain_journeys",
|
|
116530
116920
|
// #425 — a sweep: many explore missions over a targets file, one aggregated result.
|
|
116531
116921
|
"run_sweep",
|
|
116532
116922
|
// #432 — the read-only review sheet a person reads before promote_journey (bound by its content hash).
|
|
@@ -117296,7 +117686,7 @@ var tagsArg = (args) => {
|
|
|
117296
117686
|
};
|
|
117297
117687
|
|
|
117298
117688
|
// src/mcp-tools/findings.ts
|
|
117299
|
-
import { existsSync as
|
|
117689
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
117300
117690
|
import { access, readFile as readFile37 } from "node:fs/promises";
|
|
117301
117691
|
import { join as join77 } from "node:path";
|
|
117302
117692
|
function findingTools(ctx) {
|
|
@@ -117386,7 +117776,7 @@ function findingTools(ctx) {
|
|
|
117386
117776
|
};
|
|
117387
117777
|
const verifyFixOptions = (args) => {
|
|
117388
117778
|
const storageState = optPath(args, "storageState", pathRoots, { session: true });
|
|
117389
|
-
if (storageState !== void 0 && !
|
|
117779
|
+
if (storageState !== void 0 && !existsSync44(storageState)) throw new McpArgError(`storage state not found: ${storageState}`);
|
|
117390
117780
|
const replays = optInt(args, "replays", 1);
|
|
117391
117781
|
const invariantFiles = (optStringArray(args, "invariants") ?? []).map((f2, i) => optPath({ [`invariants[${i}]`]: f2 }, `invariants[${i}]`, pathRoots));
|
|
117392
117782
|
const fixtures = optPath(args, "fixtures", pathRoots);
|
|
@@ -117515,7 +117905,7 @@ function findingTools(ctx) {
|
|
|
117515
117905
|
}
|
|
117516
117906
|
|
|
117517
117907
|
// src/mcp-tools/journey.ts
|
|
117518
|
-
import { existsSync as
|
|
117908
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
117519
117909
|
function journeyTools(ctx) {
|
|
117520
117910
|
const { deps, pathRoots, credentialStore, runJourney } = ctx;
|
|
117521
117911
|
const findCaps = deps.findCapabilities ?? ((query) => findCapabilities(new JourneyRegistry(new FsJourneyStore(deps.journeysDir)), query));
|
|
@@ -117528,7 +117918,7 @@ function journeyTools(ctx) {
|
|
|
117528
117918
|
{ ...deps.environmentsFile === void 0 ? {} : { environmentsFile: deps.environmentsFile }, ...deps.targetsConfigPath === void 0 ? {} : { targetsFile: deps.targetsConfigPath } }
|
|
117529
117919
|
);
|
|
117530
117920
|
const storageState = optPath(args, "storageState", pathRoots, { session: true }) ?? environment?.storageState;
|
|
117531
|
-
if (args.storageState !== void 0 && storageState !== void 0 && !
|
|
117921
|
+
if (args.storageState !== void 0 && storageState !== void 0 && !existsSync45(storageState)) throw new McpArgError(`storage state not found: ${storageState}`);
|
|
117532
117922
|
const headed = optBool(args, "headed");
|
|
117533
117923
|
const slowMo = optInt(args, "slowMo", 0);
|
|
117534
117924
|
const recordVideo = optRecordVideo(args, pathRoots);
|
|
@@ -118142,7 +118532,7 @@ function registerMissionQueueCommands(program2, mission, deps) {
|
|
|
118142
118532
|
let invariants;
|
|
118143
118533
|
if (o.invariants !== void 0) {
|
|
118144
118534
|
try {
|
|
118145
|
-
invariants = JSON.parse(
|
|
118535
|
+
invariants = JSON.parse(readFileSync37(o.invariants, "utf8"));
|
|
118146
118536
|
} catch (e) {
|
|
118147
118537
|
refuse4("E_MISSION_QUEUE_INVARIANTS", `cannot read invariants file ${o.invariants}: ${e instanceof Error ? e.message.split("\n")[0] : String(e)}`);
|
|
118148
118538
|
return;
|
|
@@ -118899,7 +119289,7 @@ function registerUxCommands(program2, deps) {
|
|
|
118899
119289
|
}
|
|
118900
119290
|
|
|
118901
119291
|
// src/logs-retention.ts
|
|
118902
|
-
import { readFileSync as
|
|
119292
|
+
import { readFileSync as readFileSync38, readdirSync as readdirSync11, rmSync as rmSync2, rmdirSync as rmdirSync2, statSync as statSync12 } from "node:fs";
|
|
118903
119293
|
import { join as join79 } from "node:path";
|
|
118904
119294
|
var DEFAULT_LOGS_RETENTION = { ttlDays: 14, keepLatest: 50 };
|
|
118905
119295
|
var LogsConfigError = class extends Error {
|
|
@@ -118908,7 +119298,7 @@ var LogsConfigError = class extends Error {
|
|
|
118908
119298
|
function loadLogsRetention(path2 = resolveDataDir(["config.json"])) {
|
|
118909
119299
|
let raw;
|
|
118910
119300
|
try {
|
|
118911
|
-
raw =
|
|
119301
|
+
raw = readFileSync38(path2, "utf8");
|
|
118912
119302
|
} catch (e) {
|
|
118913
119303
|
if (typeof e === "object" && e !== null && "code" in e && e.code === "ENOENT") return DEFAULT_LOGS_RETENTION;
|
|
118914
119304
|
throw new LogsConfigError(`cannot read ${path2}: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -118969,8 +119359,8 @@ function pruneLogs(root2, retention, opts = {}) {
|
|
|
118969
119359
|
}
|
|
118970
119360
|
|
|
118971
119361
|
// src/logs-cli.ts
|
|
118972
|
-
import { readFileSync as
|
|
118973
|
-
import { existsSync as
|
|
119362
|
+
import { readFileSync as readFileSync39 } from "node:fs";
|
|
119363
|
+
import { existsSync as existsSync46 } from "node:fs";
|
|
118974
119364
|
var LOG_WRITING_COMMANDS = /* @__PURE__ */ new Set(["explore", "explore-author-journey", "record", "ux", "check", "run", "verify-fix", "capture"]);
|
|
118975
119365
|
function registerLogsCommands(program2, deps) {
|
|
118976
119366
|
const configPath = deps.logs?.configPath ?? resolveDataDir(["config.json"]);
|
|
@@ -119008,7 +119398,7 @@ function registerLogsCommands(program2, deps) {
|
|
|
119008
119398
|
const emit5 = (envelope) => emitJson(program2, envelope);
|
|
119009
119399
|
if (o.real === true && o.fakeAi === true) return emit5(fail("E_LOGS_ARGS", "--real and --fake-ai are mutually exclusive \u2014 pass one, not both"));
|
|
119010
119400
|
if (o.threshold !== void 0 && !(o.threshold >= 0 && o.threshold <= 1)) return emit5(fail("E_LOGS_ARGS", "--threshold must be a probability in 0..1"));
|
|
119011
|
-
if (!
|
|
119401
|
+
if (!existsSync46(signalsPathFor(o.result))) {
|
|
119012
119402
|
return emit5(fail("E_LOGS_ARGS", `no signals next to ${o.result} (${signalsPathFor(o.result)}): run explore with --log-source and --log-triage first`));
|
|
119013
119403
|
}
|
|
119014
119404
|
let secrets;
|
|
@@ -119021,7 +119411,7 @@ function registerLogsCommands(program2, deps) {
|
|
|
119021
119411
|
throw err;
|
|
119022
119412
|
}
|
|
119023
119413
|
try {
|
|
119024
|
-
const file2 = JSON.parse(
|
|
119414
|
+
const file2 = JSON.parse(readFileSync39(o.result, "utf8"));
|
|
119025
119415
|
if (typeof file2.result !== "object" || file2.result === null) return emit5(fail("E_LOGS_ARGS", `${o.result} is not a jevitate run result`));
|
|
119026
119416
|
const judge = o.real === true ? (await buildExploreGateways(deps, { real: true, fakeAi: false, jevProvider: o.jevProvider })).judge : void 0;
|
|
119027
119417
|
const updated = await triageRunResult(file2.result, o.result, {
|
|
@@ -119045,7 +119435,7 @@ result ${o.result}
|
|
|
119045
119435
|
}
|
|
119046
119436
|
|
|
119047
119437
|
// src/inbox-cli.ts
|
|
119048
|
-
import { readFileSync as
|
|
119438
|
+
import { readFileSync as readFileSync40 } from "node:fs";
|
|
119049
119439
|
import { Option as Option3 } from "commander";
|
|
119050
119440
|
var INBOX_DIR_HELP = "inbox store directory (default: ~/.jevitate/inbox \u2014 the dir `jevitate mcp` and `jevitate ui` use)";
|
|
119051
119441
|
var REDACTED = "***REDACTED***";
|
|
@@ -119153,7 +119543,7 @@ function registerInboxCommands(program2, deps) {
|
|
|
119153
119543
|
let findings;
|
|
119154
119544
|
if (o.findings !== void 0) {
|
|
119155
119545
|
try {
|
|
119156
|
-
findings = JSON.parse(
|
|
119546
|
+
findings = JSON.parse(readFileSync40(o.findings, "utf8"));
|
|
119157
119547
|
} catch (e) {
|
|
119158
119548
|
const code = `E_${commandPath(cmd).toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_INPUT`;
|
|
119159
119549
|
emitJsonOrRefusal(program2, fail(code, `cannot read --findings ${o.findings}: ${e instanceof Error ? e.message.split("\n")[0] : String(e)}`));
|