@jevitate/cli 0.18.1 → 0.19.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/bin.js +289 -54
- package/dist/build-info.generated.js +3 -3
- package/dist/journey-api.js +5 -1
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-chain.d.ts +6 -1
- package/dist/journey-chain.js +27 -10
- package/dist/journey-chain.js.map +1 -1
- package/dist/journey-cli/chain.js +4 -2
- package/dist/journey-cli/chain.js.map +1 -1
- package/dist/journey-cli/verify.js +2 -1
- package/dist/journey-cli/verify.js.map +1 -1
- package/dist/journey-readiness.js +78 -8
- package/dist/journey-readiness.js.map +1 -1
- package/dist/journey-review.js +4 -3
- package/dist/journey-review.js.map +1 -1
- package/dist/journey-verify.d.ts +8 -2
- package/dist/journey-verify.js +41 -7
- package/dist/journey-verify.js.map +1 -1
- package/dist/mcp-cli-tools.js +2 -1
- package/dist/mcp-cli-tools.js.map +1 -1
- package/package.json +11 -11
package/dist/bin.js
CHANGED
|
@@ -53836,13 +53836,14 @@ function relaxedMutationReplay(journey, m, opts = {}) {
|
|
|
53836
53836
|
return { journey, skipIndex: index };
|
|
53837
53837
|
if (m.kind === "swap-param" || m.kind === "truncate-param" || m.kind === "guard-param") {
|
|
53838
53838
|
const how = paramReplay(journey, m, opts.params ?? {});
|
|
53839
|
-
const
|
|
53839
|
+
const copy2 = how.journey === journey ? structuredClone(journey) : how.journey;
|
|
53840
|
+
const target2 = flat(copy2)[index];
|
|
53840
53841
|
if (target2 !== void 0 && "expect" in target2.step) {
|
|
53841
53842
|
const step = { ...target2.step, expect: relaxedExpect(target2.step) };
|
|
53842
53843
|
delete step.waitFor;
|
|
53843
53844
|
target2.step = step;
|
|
53844
53845
|
}
|
|
53845
|
-
return how;
|
|
53846
|
+
return { ...how, journey: copy2 };
|
|
53846
53847
|
}
|
|
53847
53848
|
if (m.kind === "block-write") {
|
|
53848
53849
|
const requests = journeyWriteSteps(journey, opts).find((w) => w.step === m.step)?.requests ?? [];
|
|
@@ -53866,6 +53867,119 @@ function relaxedMutationReplay(journey, m, opts = {}) {
|
|
|
53866
53867
|
}
|
|
53867
53868
|
return { journey: copy };
|
|
53868
53869
|
}
|
|
53870
|
+
var MAX_TARGETED_RELAXATIONS = 4;
|
|
53871
|
+
function failedSiteKey(f2) {
|
|
53872
|
+
if (f2.where === "step")
|
|
53873
|
+
return `step:${f2.step}`;
|
|
53874
|
+
if (f2.where === "step-request")
|
|
53875
|
+
return `step-request:${f2.step}:${f2.checkIndex}`;
|
|
53876
|
+
if (f2.where === "end-state")
|
|
53877
|
+
return `end-state:${f2.index}`;
|
|
53878
|
+
return "unevaluable";
|
|
53879
|
+
}
|
|
53880
|
+
function targetedMutationReplay(journey, m, targetSiteKey, relaxedSiteKeys, opts = {}) {
|
|
53881
|
+
if (relaxedSiteKeys.includes(targetSiteKey))
|
|
53882
|
+
throw new Error(`${targetSiteKey} is the target assertion \u2014 a targeted proof never relaxes it`);
|
|
53883
|
+
const base = relaxedMutationReplay(journey, m, opts);
|
|
53884
|
+
if (relaxedSiteKeys.length === 0)
|
|
53885
|
+
return base;
|
|
53886
|
+
return { ...base, journey: relaxStepSites(journey, base.journey, relaxedSiteKeys) };
|
|
53887
|
+
}
|
|
53888
|
+
function targetedControlReplay(journey, m, relaxedSiteKeys) {
|
|
53889
|
+
const own2 = flat(journey)[m.step - 1]?.step;
|
|
53890
|
+
const ownKey = own2 !== void 0 && (own2.kind === "assert" || "expect" in own2) ? [`step:${m.step}`] : [];
|
|
53891
|
+
return { journey: relaxStepSites(journey, journey, [.../* @__PURE__ */ new Set([...ownKey, ...relaxedSiteKeys])]) };
|
|
53892
|
+
}
|
|
53893
|
+
function relaxStepSites(journey, from, keys) {
|
|
53894
|
+
const byKey = new Map(journeyAssertions(journey).map((s3) => [assertionSiteKey(s3), s3]));
|
|
53895
|
+
const copy = structuredClone(from);
|
|
53896
|
+
const steps = flat(copy);
|
|
53897
|
+
for (const key2 of keys) {
|
|
53898
|
+
const match2 = /^step:([1-9][0-9]*)$/.exec(key2);
|
|
53899
|
+
if (match2 === null)
|
|
53900
|
+
throw new Error(`${key2} is not a step assertion site \u2014 a targeted proof only relaxes step:<n>`);
|
|
53901
|
+
const site = byKey.get(key2);
|
|
53902
|
+
if (site !== void 0 && site.where === "step" && site.field === "resume")
|
|
53903
|
+
throw new Error(`${key2} is a resume assertion \u2014 a targeted proof never relaxes it`);
|
|
53904
|
+
const recorded = steps[Number(match2[1]) - 1];
|
|
53905
|
+
if (recorded === void 0)
|
|
53906
|
+
throw new Error(`journey '${journey.metadata.id}' has no step ${match2[1]} to relax`);
|
|
53907
|
+
const step = { ...recorded.step };
|
|
53908
|
+
if (recorded.step.kind === "assert")
|
|
53909
|
+
step.check = { kind: "urlIncludes", text: "" };
|
|
53910
|
+
else if ("expect" in recorded.step)
|
|
53911
|
+
step.expect = relaxedExpect(recorded.step);
|
|
53912
|
+
else
|
|
53913
|
+
throw new Error(`${key2} has no page postcondition to relax`);
|
|
53914
|
+
delete step.waitFor;
|
|
53915
|
+
recorded.step = step;
|
|
53916
|
+
}
|
|
53917
|
+
return copy;
|
|
53918
|
+
}
|
|
53919
|
+
function nextTargetedRelaxation(journey, plan2, m, targetSiteKey, result, relaxedSoFar) {
|
|
53920
|
+
const target = journeyAssertions(journey).find((s3) => assertionSiteKey(s3) === targetSiteKey);
|
|
53921
|
+
if (target === void 0)
|
|
53922
|
+
return { refuse: `${targetSiteKey} is not an assertion site of this Journey` };
|
|
53923
|
+
if (classifyMutation(target, m, result) !== "cascade")
|
|
53924
|
+
return null;
|
|
53925
|
+
const first = result.failedSites[0];
|
|
53926
|
+
if (first === void 0)
|
|
53927
|
+
return { refuse: "no failed site to relax" };
|
|
53928
|
+
if (first.where === "unevaluable")
|
|
53929
|
+
return { refuse: "unevaluable end state" };
|
|
53930
|
+
if (first.where !== "step")
|
|
53931
|
+
return { refuse: `${failedSiteKey(first)} is not a step postcondition` };
|
|
53932
|
+
const key2 = `step:${first.step}`;
|
|
53933
|
+
if (!first.postcondition)
|
|
53934
|
+
return { refuse: `${key2} action failed (not a postcondition)` };
|
|
53935
|
+
if (first.step < m.step)
|
|
53936
|
+
return { refuse: "failure before the mutated step" };
|
|
53937
|
+
const step = flat(journey)[first.step - 1]?.step;
|
|
53938
|
+
if (step === void 0)
|
|
53939
|
+
return { refuse: `${key2} does not exist` };
|
|
53940
|
+
if (step.kind === "handback")
|
|
53941
|
+
return { refuse: `${key2} is a resume assertion (not a relaxable page postcondition)` };
|
|
53942
|
+
if (target.where === "step" && target.step <= first.step)
|
|
53943
|
+
return { refuse: `${key2} is not before the target ${targetSiteKey}` };
|
|
53944
|
+
if (!plan2.pairs.some((p) => p.site === key2 && p.mutation === m.id))
|
|
53945
|
+
return { refuse: `${key2} is not paired with ${m.id}` };
|
|
53946
|
+
if (relaxedSoFar.includes(key2))
|
|
53947
|
+
return { refuse: `${key2} is already relaxed` };
|
|
53948
|
+
if (relaxedSoFar.length >= MAX_TARGETED_RELAXATIONS)
|
|
53949
|
+
return { refuse: `relaxation bound ${MAX_TARGETED_RELAXATIONS} reached` };
|
|
53950
|
+
return { relax: key2 };
|
|
53951
|
+
}
|
|
53952
|
+
async function runTargetedProof(journey, plan2, m, target, initial, replay, opts = {}) {
|
|
53953
|
+
const site = assertionSiteKey(target);
|
|
53954
|
+
const relaxedSites = [];
|
|
53955
|
+
const relaxedFirst = initial.relaxed !== void 0 && initial.failedSites.some((f2) => f2.where === "step" && f2.step === m.step && f2.postcondition) && !(target.where === "step" && target.step === m.step);
|
|
53956
|
+
let run = relaxedFirst ? { outcome: initial.relaxed.outcome, failedSites: initial.relaxed.failedSites } : { outcome: initial.outcome, failedSites: initial.failedSites };
|
|
53957
|
+
for (; ; ) {
|
|
53958
|
+
const next = nextTargetedRelaxation(journey, plan2, m, site, run, relaxedSites);
|
|
53959
|
+
if (next === null)
|
|
53960
|
+
break;
|
|
53961
|
+
if ("refuse" in next)
|
|
53962
|
+
return { site, relaxedSites, outcome: run.outcome, failedSites: run.failedSites, refused: next.refuse };
|
|
53963
|
+
relaxedSites.push(next.relax);
|
|
53964
|
+
const relaxedNow = [...relaxedSites];
|
|
53965
|
+
run = await replay((j) => targetedMutationReplay(j, m, site, relaxedNow, opts), "targeted");
|
|
53966
|
+
}
|
|
53967
|
+
if (relaxedSites.length > 0 && classifyMutationPlain(target, m, run) === "sensitive") {
|
|
53968
|
+
const control = await replay((j) => targetedControlReplay(j, m, relaxedSites), "control");
|
|
53969
|
+
if (control.outcome !== "passed") {
|
|
53970
|
+
return {
|
|
53971
|
+
site,
|
|
53972
|
+
relaxedSites,
|
|
53973
|
+
outcome: run.outcome,
|
|
53974
|
+
failedSites: run.failedSites,
|
|
53975
|
+
control: control.outcome,
|
|
53976
|
+
refused: `the unmutated control replay with ${relaxedSites.join(", ")} relaxed did not pass (${control.outcome})`
|
|
53977
|
+
};
|
|
53978
|
+
}
|
|
53979
|
+
return { site, relaxedSites, outcome: run.outcome, failedSites: run.failedSites, control: control.outcome };
|
|
53980
|
+
}
|
|
53981
|
+
return { site, relaxedSites, outcome: run.outcome, failedSites: run.failedSites };
|
|
53982
|
+
}
|
|
53869
53983
|
function needsRelaxedReplay(plan2, m, result) {
|
|
53870
53984
|
if (result.outcome !== "failed")
|
|
53871
53985
|
return false;
|
|
@@ -53875,8 +53989,18 @@ function needsRelaxedReplay(plan2, m, result) {
|
|
|
53875
53989
|
return plan2.pairs.some((p) => p.mutation === m.id && p.site !== own2);
|
|
53876
53990
|
}
|
|
53877
53991
|
function classifyMutation(site, m, result) {
|
|
53992
|
+
const verdict = classifyMutationPlain(site, m, result);
|
|
53993
|
+
if (verdict !== "cascade")
|
|
53994
|
+
return verdict;
|
|
53995
|
+
const proof = result.targeted?.find((t) => t.site === assertionSiteKey(site));
|
|
53996
|
+
if (proof === void 0 || proof.refused !== void 0)
|
|
53997
|
+
return "cascade";
|
|
53998
|
+
const targeted = classifyMutationPlain(site, m, { outcome: proof.outcome, failedSites: proof.failedSites });
|
|
53999
|
+
return targeted === "sensitive" || targeted === "insensitive" ? targeted : "cascade";
|
|
54000
|
+
}
|
|
54001
|
+
function classifyMutationPlain(site, m, result) {
|
|
53878
54002
|
if (result.relaxed !== void 0 && result.failedSites.some((f2) => f2.where === "step" && f2.step === m.step && f2.postcondition) && !(site.where === "step" && site.step === m.step)) {
|
|
53879
|
-
return
|
|
54003
|
+
return classifyMutationPlain(site, m, { outcome: result.relaxed.outcome, failedSites: result.relaxed.failedSites });
|
|
53880
54004
|
}
|
|
53881
54005
|
if (result.outcome === "passed")
|
|
53882
54006
|
return "insensitive";
|
|
@@ -53902,6 +54026,7 @@ function classifyMutation(site, m, result) {
|
|
|
53902
54026
|
}
|
|
53903
54027
|
var PRECEDENCE = ["sensitive", "insensitive", "cascade", "not-applied", "error"];
|
|
53904
54028
|
function judgeAssertions(journey, plan2, results) {
|
|
54029
|
+
const proofFor = (m, key2) => results.get(m.id)?.targeted?.find((t) => t.site === key2);
|
|
53905
54030
|
return journeyAssertions(journey).map((site) => {
|
|
53906
54031
|
const key2 = assertionSiteKey(site);
|
|
53907
54032
|
const paired = plan2.mutations.filter((m) => plan2.pairs.some((p) => p.site === key2 && p.mutation === m.id));
|
|
@@ -53912,7 +54037,16 @@ function judgeAssertions(journey, plan2, results) {
|
|
|
53912
54037
|
const first = verdicts.find((x) => x.v === v);
|
|
53913
54038
|
if (first === void 0)
|
|
53914
54039
|
continue;
|
|
53915
|
-
|
|
54040
|
+
if (v === "sensitive") {
|
|
54041
|
+
const proof = proofFor(first.m, key2);
|
|
54042
|
+
return proof !== void 0 && proof.refused === void 0 ? { site: key2, verdict: v, provedBy: first.m.id, relaxedSites: proof.relaxedSites } : { site: key2, verdict: v, provedBy: first.m.id };
|
|
54043
|
+
}
|
|
54044
|
+
if (v === "cascade") {
|
|
54045
|
+
const refusal = paired.map((m) => proofFor(m, key2)).find((t) => t !== void 0 && t.refused !== void 0);
|
|
54046
|
+
if (refusal !== void 0)
|
|
54047
|
+
return { site: key2, verdict: v, targetedRefusal: refusal.refused };
|
|
54048
|
+
}
|
|
54049
|
+
return { site: key2, verdict: v };
|
|
53916
54050
|
}
|
|
53917
54051
|
return { site: key2, verdict: "error" };
|
|
53918
54052
|
});
|
|
@@ -53930,6 +54064,10 @@ function mutationProofVerdict(input2) {
|
|
|
53930
54064
|
return { verdict: "insensitive" };
|
|
53931
54065
|
if (paired.every((a) => a.verdict === "sensitive"))
|
|
53932
54066
|
return { verdict: "proven" };
|
|
54067
|
+
const refusals = input2.assertions.map((a) => a.targetedRefusal).filter((r) => r !== void 0);
|
|
54068
|
+
if (refusals.length > 0) {
|
|
54069
|
+
return { verdict: "inconclusive", reason: `some paired assertions were neither proven nor shown vacuous (cascade, not-applied or error); a targeted proof was refused: ${refusals[0]}` };
|
|
54070
|
+
}
|
|
53933
54071
|
return { verdict: "inconclusive", reason: "some paired assertions were neither proven nor shown vacuous (cascade, not-applied or error)" };
|
|
53934
54072
|
}
|
|
53935
54073
|
|
|
@@ -55383,7 +55521,13 @@ var ReviewChangeSchema = external_exports.discriminatedUnion("kind", [
|
|
|
55383
55521
|
sideEffects: DiffSchema
|
|
55384
55522
|
}).strict()
|
|
55385
55523
|
]);
|
|
55386
|
-
var ReviewAttentionSchema = external_exports.object({
|
|
55524
|
+
var ReviewAttentionSchema = external_exports.object({
|
|
55525
|
+
severity: external_exports.enum(["warn", "info"]),
|
|
55526
|
+
text: external_exports.string(),
|
|
55527
|
+
hint: external_exports.string().optional(),
|
|
55528
|
+
/** #608: a person's catalog approval settles this item — readiness lists it as awaiting-human, never as a failure. */
|
|
55529
|
+
settledBy: external_exports.enum(["catalog-approval"]).optional()
|
|
55530
|
+
}).strict();
|
|
55387
55531
|
var JourneyReviewSchema = external_exports.object({
|
|
55388
55532
|
id: external_exports.string(),
|
|
55389
55533
|
name: external_exports.string(),
|
|
@@ -62390,9 +62534,9 @@ function hostStarvedFailure(failure3, health) {
|
|
|
62390
62534
|
}
|
|
62391
62535
|
|
|
62392
62536
|
// src/build-info.generated.ts
|
|
62393
|
-
var GENERATED_COMMIT = "
|
|
62394
|
-
var GENERATED_TREE = "
|
|
62395
|
-
var GENERATED_BUILT_AT = "2026-10-
|
|
62537
|
+
var GENERATED_COMMIT = "0a3d2f5";
|
|
62538
|
+
var GENERATED_TREE = "963f59f";
|
|
62539
|
+
var GENERATED_BUILT_AT = "2026-10-19T17:41:04.191Z";
|
|
62396
62540
|
|
|
62397
62541
|
// src/version.ts
|
|
62398
62542
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
@@ -62414,13 +62558,13 @@ function readCliVersion() {
|
|
|
62414
62558
|
|
|
62415
62559
|
// src/engine.ts
|
|
62416
62560
|
function bundledCommit() {
|
|
62417
|
-
return true ? "
|
|
62561
|
+
return true ? "0a3d2f5" : void 0;
|
|
62418
62562
|
}
|
|
62419
62563
|
function bundledBuiltAt() {
|
|
62420
|
-
return true ? "2026-10-
|
|
62564
|
+
return true ? "2026-10-19T17:41:04.191Z" : void 0;
|
|
62421
62565
|
}
|
|
62422
62566
|
function bundledTree() {
|
|
62423
|
-
return true ? "
|
|
62567
|
+
return true ? "963f59f" : void 0;
|
|
62424
62568
|
}
|
|
62425
62569
|
function currentBuildTree() {
|
|
62426
62570
|
return bundledTree() ?? GENERATED_TREE;
|
|
@@ -80381,7 +80525,7 @@ function describeFile(step) {
|
|
|
80381
80525
|
}
|
|
80382
80526
|
function buildAttention(r, weakEndState, goal) {
|
|
80383
80527
|
const out = [];
|
|
80384
|
-
const warn = (text2, hint2) => void out.push({ severity: "warn", text: text2, ...hint2 === void 0 ? {} : { hint: hint2 } });
|
|
80528
|
+
const warn = (text2, hint2, settledBy) => void out.push({ severity: "warn", text: text2, ...hint2 === void 0 ? {} : { hint: hint2 }, ...settledBy === void 0 ? {} : { settledBy } });
|
|
80385
80529
|
const info = (text2, hint2) => void out.push({ severity: "info", text: text2, ...hint2 === void 0 ? {} : { hint: hint2 } });
|
|
80386
80530
|
const weakSteps = [...new Set(r.proof.stepAssertions.filter((a) => a.weak).map((a) => a.step))];
|
|
80387
80531
|
if (weakSteps.length === 1) warn(`Step ${stepRanges(weakSteps)} proves nothing: its check passes even if the step fails`);
|
|
@@ -80402,12 +80546,12 @@ function buildAttention(r, weakEndState, goal) {
|
|
|
80402
80546
|
else info(`${text2}, exempted by allowControl`);
|
|
80403
80547
|
}
|
|
80404
80548
|
if (r.catalog !== void 0) {
|
|
80405
|
-
if (r.catalog.unvetted.length > 0) warn(`Unvetted catalog links: ${r.catalog.unvetted.join(", ")}`, `approve them, or promote with --accept-unvetted "<reason>"
|
|
80549
|
+
if (r.catalog.unvetted.length > 0) warn(`Unvetted catalog links: ${r.catalog.unvetted.join(", ")}`, `approve them, or promote with --accept-unvetted "<reason>"`, "catalog-approval");
|
|
80406
80550
|
if (r.catalog.needsReReview.length > 0) warn(`Catalog links need re-review: ${r.catalog.needsReReview.join("; ")}`);
|
|
80407
80551
|
}
|
|
80408
80552
|
for (const f2 of r.findings ?? []) {
|
|
80409
80553
|
if (f2.analyzer === "catalog-analysis") continue;
|
|
80410
|
-
if (f2.severity !== "info") warn(f2.message, f2.fix);
|
|
80554
|
+
if (f2.severity !== "info") warn(f2.message, f2.fix, f2.analyzer === "catalog-links" && f2.code === "journey.unvetted" ? "catalog-approval" : void 0);
|
|
80411
80555
|
else if (f2.analyzer === "readiness" || f2.analyzer === "readiness-jev") info(f2.message, f2.fix);
|
|
80412
80556
|
}
|
|
80413
80557
|
const c = r.changeSinceApproval;
|
|
@@ -95099,7 +95243,8 @@ async function runJourneyProgrammatically(opts, mutation2 = {}) {
|
|
|
95099
95243
|
let result;
|
|
95100
95244
|
let runSecrets2 = secrets;
|
|
95101
95245
|
try {
|
|
95102
|
-
const
|
|
95246
|
+
const replayParams = replayed === journey ? params : prefixParams(journey, replayed, params);
|
|
95247
|
+
const raw = await outcomeChecks.run(actor, () => runner.run({ journey: replayed, params: replayParams, policy }));
|
|
95103
95248
|
runSecrets2 = runSecretValues(secrets, raw);
|
|
95104
95249
|
result = redactSecretValues(raw, runSecrets2);
|
|
95105
95250
|
} finally {
|
|
@@ -108463,6 +108608,9 @@ function redactReason(reason, params, names = TEXT_PARAMS) {
|
|
|
108463
108608
|
}
|
|
108464
108609
|
return out;
|
|
108465
108610
|
}
|
|
108611
|
+
function redactProducerParams(reason, params) {
|
|
108612
|
+
return params === void 0 ? reason : redactReason(reason, params, Object.keys(params));
|
|
108613
|
+
}
|
|
108466
108614
|
function chainSucceeded(result) {
|
|
108467
108615
|
return result.unmatched.length === 0 && result.runs.every((run) => run.outcome === "ok");
|
|
108468
108616
|
}
|
|
@@ -108553,10 +108701,10 @@ async function runHandoffChain(inputs, outputs, fromJourney, fromOutput, request
|
|
|
108553
108701
|
...identity,
|
|
108554
108702
|
outcome: result.outcome,
|
|
108555
108703
|
...stamp,
|
|
108556
|
-
..."reason" in result ? { reason: redactReason(result.reason, params, redactors) } : {}
|
|
108704
|
+
..."reason" in result ? { reason: redactProducerParams(redactReason(result.reason, params, redactors), opts.params) } : {}
|
|
108557
108705
|
});
|
|
108558
108706
|
} catch (err) {
|
|
108559
|
-
runs.push({ ...identity, outcome: "error", ...stamp, reason: redactReason(err instanceof Error ? err.message : String(err), params, redactors) });
|
|
108707
|
+
runs.push({ ...identity, outcome: "error", ...stamp, reason: redactProducerParams(redactReason(err instanceof Error ? err.message : String(err), params, redactors), opts.params) });
|
|
108560
108708
|
}
|
|
108561
108709
|
}
|
|
108562
108710
|
return { from: { journey: opts.from, outcome: "ok", records: records.length }, runs, unmatched, rejected };
|
|
@@ -108568,9 +108716,15 @@ async function runJourneyChain(opts, deps = {}) {
|
|
|
108568
108716
|
const toJourney = await registry3.get(opts.to);
|
|
108569
108717
|
if (toJourney === null) throw new UnknownJourneyError(`unknown journey '${opts.to}'`);
|
|
108570
108718
|
const inputs = toJourney.metadata.inputs;
|
|
108571
|
-
const
|
|
108572
|
-
|
|
108573
|
-
|
|
108719
|
+
const fromJourney = await registry3.get(opts.from);
|
|
108720
|
+
if (fromJourney === null) throw new UnknownJourneyError(`unknown journey '${opts.from}'`);
|
|
108721
|
+
const producerParams = { ...opts.params ?? {} };
|
|
108722
|
+
try {
|
|
108723
|
+
validateParams(journeyParamSchema(fromJourney), producerParams);
|
|
108724
|
+
} catch (err) {
|
|
108725
|
+
if (err instanceof ParamValidationError) throw new JourneyChainError("E_CHAIN_PARAMS", err.message);
|
|
108726
|
+
throw err;
|
|
108727
|
+
}
|
|
108574
108728
|
if (opts.requirePromoted === true) {
|
|
108575
108729
|
for (const j of [fromJourney, toJourney]) {
|
|
108576
108730
|
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)`);
|
|
@@ -108585,9 +108739,9 @@ async function runJourneyChain(opts, deps = {}) {
|
|
|
108585
108739
|
handoff2 = { inputs, outputs };
|
|
108586
108740
|
}
|
|
108587
108741
|
const requests = handoff2 === void 0 ? parseChainRequests(opts.requests) : void 0;
|
|
108588
|
-
const fromResult = await runner({ ...shared3, id: opts.from, params:
|
|
108742
|
+
const fromResult = await runner({ ...shared3, id: opts.from, params: producerParams });
|
|
108589
108743
|
if (fromResult.outcome !== "ok") {
|
|
108590
|
-
const reason = "reason" in fromResult ? fromResult.reason : void 0;
|
|
108744
|
+
const reason = "reason" in fromResult ? redactProducerParams(fromResult.reason, opts.params) : void 0;
|
|
108591
108745
|
throw new JourneyChainError(
|
|
108592
108746
|
"E_CHAIN_FROM_FAILED",
|
|
108593
108747
|
`discover Journey '${opts.from}' did not run ok (${fromResult.outcome})${reason === void 0 ? "" : `: ${reason}`}`
|
|
@@ -108621,10 +108775,10 @@ async function runJourneyChain(opts, deps = {}) {
|
|
|
108621
108775
|
commentId: request.commentId,
|
|
108622
108776
|
account: request.account,
|
|
108623
108777
|
outcome: result.outcome,
|
|
108624
|
-
..."reason" in result ? { reason: redactReason(result.reason, mapped.params) } : {}
|
|
108778
|
+
..."reason" in result ? { reason: redactProducerParams(redactReason(result.reason, mapped.params), opts.params) } : {}
|
|
108625
108779
|
});
|
|
108626
108780
|
} catch (err) {
|
|
108627
|
-
runs.push({ commentId: request.commentId, account: request.account, outcome: "error", reason: redactReason(err instanceof Error ? err.message : String(err), mapped.params) });
|
|
108781
|
+
runs.push({ commentId: request.commentId, account: request.account, outcome: "error", reason: redactProducerParams(redactReason(err instanceof Error ? err.message : String(err), mapped.params), opts.params) });
|
|
108628
108782
|
}
|
|
108629
108783
|
}
|
|
108630
108784
|
return { from: { journey: opts.from, outcome: "ok", records: count }, runs, unmatched };
|
|
@@ -108632,12 +108786,12 @@ async function runJourneyChain(opts, deps = {}) {
|
|
|
108632
108786
|
|
|
108633
108787
|
// src/journey-cli/chain.ts
|
|
108634
108788
|
function registerJourneyChain(journey, program2, deps) {
|
|
108635
|
-
withReplayAllowFlag(withEnvironmentFlags(withBrowserLaunchFlags(withEmulationFlags(withProjectFlags(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>", DEPRECATED_DIR_HELP).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() {
|
|
108789
|
+
withReplayAllowFlag(withEnvironmentFlags(withBrowserLaunchFlags(withEmulationFlags(withProjectFlags(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("--param <kv>", "param as key=value (repeatable)", collectParam, {}).option("--dir <path>", DEPRECATED_DIR_HELP).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() {
|
|
108636
108790
|
const locationFlags = this.opts();
|
|
108637
108791
|
const layout = journeyLayout(program2, deps, { dir: locationFlags.dir, project: locationFlags.project, journeysDir: locationFlags.journeysDir });
|
|
108638
108792
|
if (layout === null) return;
|
|
108639
108793
|
const chainJourneysDir = layout.journeysDir;
|
|
108640
|
-
const { from, to, requests: requestsFile, storageState: storageStateFlag, json: json2, allowDraft } = this.opts();
|
|
108794
|
+
const { from, to, requests: requestsFile, storageState: storageStateFlag, json: json2, allowDraft, param } = this.opts();
|
|
108641
108795
|
const { env: envName, baseUrl } = this.opts();
|
|
108642
108796
|
let environment;
|
|
108643
108797
|
let allow;
|
|
@@ -108685,6 +108839,7 @@ function registerJourneyChain(journey, program2, deps) {
|
|
|
108685
108839
|
from,
|
|
108686
108840
|
to,
|
|
108687
108841
|
requests,
|
|
108842
|
+
...Object.keys(param).length === 0 ? {} : { params: param },
|
|
108688
108843
|
dir: chainJourneysDir,
|
|
108689
108844
|
requirePromoted: allowDraft !== true,
|
|
108690
108845
|
...siteGate === void 0 ? {} : { siteGate },
|
|
@@ -109084,12 +109239,12 @@ async function verifyJourneyMutations(opts, run = runJourneyProgrammatically) {
|
|
|
109084
109239
|
const mutations = [];
|
|
109085
109240
|
if (base.outcome === "ok") {
|
|
109086
109241
|
const replayOpts2 = { ...lintOpts, params: opts.params };
|
|
109087
|
-
const
|
|
109242
|
+
const runReplay = async (m, describe6) => {
|
|
109088
109243
|
try {
|
|
109089
|
-
const how = describe6(journey
|
|
109244
|
+
const how = describe6(journey);
|
|
109090
109245
|
const r = await run(how.params === void 0 ? runOpts : { ...runOpts, params: { ...how.params } }, {
|
|
109091
109246
|
structuredFailures: true,
|
|
109092
|
-
...how.journey === journey ? {} : { mutateJourney: (j) => describe6(j
|
|
109247
|
+
...how.journey === journey ? {} : { mutateJourney: (j) => describe6(j).journey },
|
|
109093
109248
|
...how.skipIndex === void 0 ? {} : { skipStep: (i) => i === how.skipIndex },
|
|
109094
109249
|
...how.swapSelectAtStep === void 0 ? {} : { selectAlternativeAtStep: how.swapSelectAtStep },
|
|
109095
109250
|
...how.blockIndex === void 0 ? {} : { blockWritesAtStep: how.blockIndex }
|
|
@@ -109117,9 +109272,19 @@ async function verifyJourneyMutations(opts, run = runJourneyProgrammatically) {
|
|
|
109117
109272
|
return { outcome: "error", failedSites: [], reason: err instanceof Error ? err.message : String(err) };
|
|
109118
109273
|
}
|
|
109119
109274
|
};
|
|
109275
|
+
const replay = (m, describe6) => runReplay(m, (j) => describe6(j, m, replayOpts2));
|
|
109276
|
+
const siteByKey = new Map(sites.map((s3) => [assertionSiteKey(s3), s3]));
|
|
109120
109277
|
for (const m of plan2.mutations) {
|
|
109121
109278
|
const first = await replay(m, mutationReplay);
|
|
109122
109279
|
const relaxed2 = needsRelaxedReplay(plan2, m, first) ? await replay(m, relaxedMutationReplay) : void 0;
|
|
109280
|
+
const initial = { outcome: first.outcome, failedSites: first.failedSites, ...relaxed2 === void 0 ? {} : { relaxed: relaxed2 } };
|
|
109281
|
+
const targeted = [];
|
|
109282
|
+
for (const pair of plan2.pairs) {
|
|
109283
|
+
if (pair.mutation !== m.id) continue;
|
|
109284
|
+
const site = siteByKey.get(pair.site);
|
|
109285
|
+
if (site === void 0 || classifyMutation(site, m, initial) !== "cascade") continue;
|
|
109286
|
+
targeted.push(await runTargetedProof(journey, plan2, m, site, initial, (describe6) => runReplay(m, describe6), replayOpts2));
|
|
109287
|
+
}
|
|
109123
109288
|
mutations.push({
|
|
109124
109289
|
kind: m.kind,
|
|
109125
109290
|
step: m.step,
|
|
@@ -109127,15 +109292,26 @@ async function verifyJourneyMutations(opts, run = runJourneyProgrammatically) {
|
|
|
109127
109292
|
...m.param === void 0 ? {} : { param: m.param },
|
|
109128
109293
|
...m.source === void 0 ? {} : { source: m.source },
|
|
109129
109294
|
...first,
|
|
109130
|
-
...relaxed2 === void 0 ? {} : { relaxed: relaxed2 }
|
|
109295
|
+
...relaxed2 === void 0 ? {} : { relaxed: relaxed2 },
|
|
109296
|
+
...targeted.length === 0 ? {} : { targeted }
|
|
109131
109297
|
});
|
|
109132
109298
|
}
|
|
109133
109299
|
}
|
|
109134
109300
|
const results = new Map(
|
|
109135
|
-
mutations.map((m) => [
|
|
109301
|
+
mutations.map((m) => [
|
|
109302
|
+
m.id,
|
|
109303
|
+
{ outcome: m.outcome, failedSites: m.failedSites, ...m.relaxed === void 0 ? {} : { relaxed: m.relaxed }, ...m.targeted === void 0 ? {} : { targeted: m.targeted } }
|
|
109304
|
+
])
|
|
109136
109305
|
);
|
|
109137
109306
|
const judged = judgeAssertions(journey, plan2, results);
|
|
109138
|
-
const assertions = judged.map((a) => ({
|
|
109307
|
+
const assertions = judged.map((a) => ({
|
|
109308
|
+
site: a.site,
|
|
109309
|
+
check: checkOf.get(a.site) ?? a.site,
|
|
109310
|
+
verdict: a.verdict,
|
|
109311
|
+
...a.provedBy === void 0 ? {} : { provedBy: a.provedBy },
|
|
109312
|
+
...a.relaxedSites === void 0 ? {} : { relaxedSites: a.relaxedSites },
|
|
109313
|
+
...a.targetedRefusal === void 0 ? {} : { targetedRefusal: a.targetedRefusal }
|
|
109314
|
+
}));
|
|
109139
109315
|
const { verdict, reason } = mutationProofVerdict({ basePassed: base.outcome === "ok", mutations, assertions: judged });
|
|
109140
109316
|
const count = (v) => assertions.filter((a) => a.verdict === v).length;
|
|
109141
109317
|
const report2 = {
|
|
@@ -109152,7 +109328,9 @@ async function verifyJourneyMutations(opts, run = runJourneyProgrammatically) {
|
|
|
109152
109328
|
cascade: count("cascade"),
|
|
109153
109329
|
notApplied: count("not-applied"),
|
|
109154
109330
|
error: count("error"),
|
|
109155
|
-
unpaired: count("unpaired")
|
|
109331
|
+
unpaired: count("unpaired"),
|
|
109332
|
+
// #609: assertions proven sensitive through a targeted proof that relaxed earlier sites.
|
|
109333
|
+
targeted: assertions.filter((a) => (a.relaxedSites?.length ?? 0) > 0).length
|
|
109156
109334
|
}
|
|
109157
109335
|
};
|
|
109158
109336
|
const redacted = redactSecretParams(report2, journey, opts.params);
|
|
@@ -109168,7 +109346,10 @@ async function verifyJourneyMutations(opts, run = runJourneyProgrammatically) {
|
|
|
109168
109346
|
return redacted;
|
|
109169
109347
|
}
|
|
109170
109348
|
function verifyAssertionLine(a) {
|
|
109171
|
-
|
|
109349
|
+
const relaxed2 = a.relaxedSites === void 0 || a.relaxedSites.length === 0 ? "" : `, relaxed ${a.relaxedSites.join(", ")}`;
|
|
109350
|
+
const proved = a.provedBy === void 0 ? "" : ` (proved by ${a.provedBy}${relaxed2})`;
|
|
109351
|
+
const refused = a.targetedRefusal === void 0 ? "" : ` (targeted proof refused: ${a.targetedRefusal})`;
|
|
109352
|
+
return `${a.verdict.padEnd(11)} ${a.site.padEnd(18)} ${a.check}${proved}${refused}`;
|
|
109172
109353
|
}
|
|
109173
109354
|
|
|
109174
109355
|
// src/journey-readiness.ts
|
|
@@ -109181,7 +109362,7 @@ var ReadinessError = class extends Error {
|
|
|
109181
109362
|
}
|
|
109182
109363
|
};
|
|
109183
109364
|
var REQUIRED_PROOF_CHECK = "proof";
|
|
109184
|
-
function resolveTarget2(opts, deps, required2) {
|
|
109365
|
+
function resolveTarget2(opts, deps, required2, declared) {
|
|
109185
109366
|
let environment;
|
|
109186
109367
|
if (opts.env !== void 0 || opts.baseUrl !== void 0) {
|
|
109187
109368
|
environment = environmentFromFlags(
|
|
@@ -109199,6 +109380,10 @@ function resolveTarget2(opts, deps, required2) {
|
|
|
109199
109380
|
if (missing.length > 0) {
|
|
109200
109381
|
throw new ReadinessError("E_READINESS_PARAMS", `missing required param(s): ${missing.join(", ")}`);
|
|
109201
109382
|
}
|
|
109383
|
+
const unknown2 = Object.keys(opts.params ?? {}).filter((name) => !declared.includes(name));
|
|
109384
|
+
if (unknown2.length > 0) {
|
|
109385
|
+
throw new ReadinessError("E_READINESS_PARAMS", `unknown param(s): ${unknown2.join(", ")}`);
|
|
109386
|
+
}
|
|
109202
109387
|
return environment;
|
|
109203
109388
|
}
|
|
109204
109389
|
function requiredParams(journey, pair, hasRequests) {
|
|
@@ -109241,7 +109426,7 @@ function boundaryCheck(ctx) {
|
|
|
109241
109426
|
return ctx.journey.metadata.boundary === void 0 ? { check: "boundary", journey: ctx.id, state: "not-run", detail: "no prepare-only boundary declared" } : { check: "boundary", journey: ctx.id, state: "pass", detail: "a prepare-only boundary is declared" };
|
|
109242
109427
|
}
|
|
109243
109428
|
function reviewStrictCheck(ctx) {
|
|
109244
|
-
const warns = (ctx.review.attention ?? []).filter((a) => a.severity === "warn");
|
|
109429
|
+
const warns = (ctx.review.attention ?? []).filter((a) => a.severity === "warn" && !(a.settledBy === "catalog-approval" && ctx.review.catalog !== void 0));
|
|
109245
109430
|
if (warns.length > 0) {
|
|
109246
109431
|
return {
|
|
109247
109432
|
check: { check: "review-strict", journey: ctx.id, state: "fail", detail: warns.map((a) => a.text).join("; ") },
|
|
@@ -109308,8 +109493,10 @@ function proofCheck(ctx, journeysDir, cwd) {
|
|
|
109308
109493
|
};
|
|
109309
109494
|
}
|
|
109310
109495
|
if (verify2.verdict === "proven") {
|
|
109311
|
-
const
|
|
109312
|
-
|
|
109496
|
+
const targeted = verify2.summary.targeted ?? 0;
|
|
109497
|
+
const passed = Object.entries(verify2.summary).filter(([k]) => k !== "targeted").reduce((a, [, b2]) => a + b2, 0);
|
|
109498
|
+
const detail = targeted === 0 ? `proven ${passed}/${passed}` : `proven ${passed}/${passed}, ${targeted} through a targeted proof (earlier defenses relaxed one at a time; see the verify report)`;
|
|
109499
|
+
return { check: { check: "proof", journey: ctx.id, state: "pass", detail, evidence } };
|
|
109313
109500
|
}
|
|
109314
109501
|
if (verify2.verdict === "insensitive") {
|
|
109315
109502
|
return {
|
|
@@ -109320,10 +109507,27 @@ function proofCheck(ctx, journeysDir, cwd) {
|
|
|
109320
109507
|
if (nothingToMutate(ctx.journey, verify2.summary)) {
|
|
109321
109508
|
return { check: { check: "proof", journey: ctx.id, state: "pass", detail: "read-only with no inputs: nothing a mutation could break", evidence } };
|
|
109322
109509
|
}
|
|
109323
|
-
return {
|
|
109510
|
+
return {
|
|
109511
|
+
check: { check: "proof", journey: ctx.id, state: "inconclusive", detail: verify2.reason ?? `proof verdict ${verify2.verdict}`, evidence },
|
|
109512
|
+
blocker: { check: "proof", journey: ctx.id, why: inconclusiveProofGuidance(verify2.reason ?? ""), next: `jevitate journey verify ${ctx.id} --mutate` }
|
|
109513
|
+
};
|
|
109514
|
+
}
|
|
109515
|
+
var TARGETED_REFUSAL_MARKER = "a targeted proof was refused: ";
|
|
109516
|
+
function inconclusiveProofGuidance(reason) {
|
|
109517
|
+
const at3 = reason.indexOf(TARGETED_REFUSAL_MARKER);
|
|
109518
|
+
if (at3 < 0) return "inspect the cascade assertions in the verify report";
|
|
109519
|
+
const refusal = reason.slice(at3 + TARGETED_REFUSAL_MARKER.length).trim();
|
|
109520
|
+
const unpaired = /^(\S+) is not paired with (\S+)$/.exec(refusal);
|
|
109521
|
+
if (unpaired !== null) {
|
|
109522
|
+
return `declare the earlier check ${unpaired[1]} as a defense of ${unpaired[2]} with a metadata.mutationPairs entry {check:'${unpaired[1]}', mustFailWhen:'${unpaired[2]}'}, then re-run verify`;
|
|
109523
|
+
}
|
|
109524
|
+
const bound2 = /relaxation bound (\d+)/.exec(refusal);
|
|
109525
|
+
if (bound2 !== null) return `reduce the layered checks between the mutation and the target (relaxation bound ${bound2[1]})`;
|
|
109526
|
+
if (refusal.includes("action failed")) return "the mutated value makes an earlier action impossible, so that target cannot be proven independently \u2014 keep the check; it stays inconclusive by design";
|
|
109527
|
+
return "inspect the cascade assertions in the verify report";
|
|
109324
109528
|
}
|
|
109325
109529
|
function nothingToMutate(journey, summary2) {
|
|
109326
|
-
const paired = Object.entries(summary2).filter(([k]) => k !== "unpaired").reduce((n3, [, v]) => n3 + v, 0);
|
|
109530
|
+
const paired = Object.entries(summary2).filter(([k]) => k !== "unpaired" && k !== "targeted").reduce((n3, [, v]) => n3 + v, 0);
|
|
109327
109531
|
return (summary2.unpaired ?? 0) > 0 && paired === 0 && journeyWriteSteps(journey).length === 0 && journeyParamSchema(journey).required.length === 0;
|
|
109328
109532
|
}
|
|
109329
109533
|
function relativeEvidence(cwd, path2) {
|
|
@@ -109409,21 +109613,38 @@ async function runJourneyReadiness(opts, deps = {}) {
|
|
|
109409
109613
|
const pair = opts.with !== void 0;
|
|
109410
109614
|
let environment;
|
|
109411
109615
|
let replay;
|
|
109616
|
+
let boundConsumerParams;
|
|
109412
109617
|
if (mode !== "report") {
|
|
109413
|
-
|
|
109618
|
+
const producerSchema = journeyParamSchema(contexts[0].journey).required;
|
|
109619
|
+
environment = resolveTarget2(opts, deps, requiredParams(contexts[0].journey, pair, opts.requests !== void 0), producerSchema);
|
|
109414
109620
|
const params = { ...opts.params ?? {} };
|
|
109415
109621
|
try {
|
|
109416
109622
|
if (pair) {
|
|
109417
|
-
const chained = await chain(
|
|
109418
|
-
|
|
109419
|
-
|
|
109420
|
-
|
|
109421
|
-
|
|
109422
|
-
|
|
109423
|
-
|
|
109424
|
-
|
|
109425
|
-
|
|
109426
|
-
|
|
109623
|
+
const chained = await chain(
|
|
109624
|
+
{
|
|
109625
|
+
from: opts.id,
|
|
109626
|
+
to: opts.with,
|
|
109627
|
+
requests: opts.requests ?? "",
|
|
109628
|
+
params: { ...opts.params ?? {} },
|
|
109629
|
+
dir: opts.journeysDir,
|
|
109630
|
+
environment,
|
|
109631
|
+
...opts.storageState === void 0 ? {} : { storageState: opts.storageState },
|
|
109632
|
+
...opts.browser === void 0 ? {} : { browser: opts.browser },
|
|
109633
|
+
...opts.browserPortFactory === void 0 ? {} : { browserPortFactory: opts.browserPortFactory }
|
|
109634
|
+
},
|
|
109635
|
+
{
|
|
109636
|
+
// #608: the consumer's proof must run with the params the chain actually bound for it
|
|
109637
|
+
// (record fields + request), captured from the first consumer run; names and outcomes
|
|
109638
|
+
// are all the chain itself returns.
|
|
109639
|
+
runJourney: async (chainOpts) => {
|
|
109640
|
+
const result = await run(chainOpts);
|
|
109641
|
+
if (chainOpts.id === opts.with && boundConsumerParams === void 0) {
|
|
109642
|
+
boundConsumerParams = { ...chainOpts.params };
|
|
109643
|
+
}
|
|
109644
|
+
return result;
|
|
109645
|
+
}
|
|
109646
|
+
}
|
|
109647
|
+
);
|
|
109427
109648
|
replay = pairReplay(chained);
|
|
109428
109649
|
} else {
|
|
109429
109650
|
const result = await run({
|
|
@@ -109443,11 +109664,23 @@ async function runJourneyReadiness(opts, deps = {}) {
|
|
|
109443
109664
|
}
|
|
109444
109665
|
if (mode === "prove") {
|
|
109445
109666
|
for (const ctx of contexts) {
|
|
109667
|
+
const consumer = pair && ctx.id === opts.with;
|
|
109668
|
+
if (consumer && boundConsumerParams === void 0) {
|
|
109669
|
+
ctx.review = {
|
|
109670
|
+
...ctx.review,
|
|
109671
|
+
proof: {
|
|
109672
|
+
...ctx.review.proof,
|
|
109673
|
+
verify: { status: "not-verified", hint: `the chain bound no request for '${ctx.id}' \u2014 supply a --requests line that matches a discovered record` }
|
|
109674
|
+
}
|
|
109675
|
+
};
|
|
109676
|
+
continue;
|
|
109677
|
+
}
|
|
109678
|
+
const proofParams = consumer ? boundConsumerParams : params;
|
|
109446
109679
|
try {
|
|
109447
109680
|
await verify2({
|
|
109448
109681
|
dir: opts.journeysDir,
|
|
109449
109682
|
id: ctx.id,
|
|
109450
|
-
params,
|
|
109683
|
+
params: proofParams,
|
|
109451
109684
|
environment,
|
|
109452
109685
|
...opts.storageState === void 0 ? {} : { storageState: opts.storageState },
|
|
109453
109686
|
...opts.browser === void 0 ? {} : { browser: opts.browser },
|
|
@@ -110800,8 +111033,9 @@ function registerJourneyVerify(journey, program2, deps) {
|
|
|
110800
111033
|
for (const a of report2.assertions) out?.(`${verifyAssertionLine(a)}
|
|
110801
111034
|
`);
|
|
110802
111035
|
const s3 = report2.summary;
|
|
111036
|
+
const targeted = s3.targeted > 0 ? `, ${s3.targeted} targeted` : "";
|
|
110803
111037
|
out?.(
|
|
110804
|
-
`${report2.verdict} \u2014 journey '${report2.journeyId}': ${s3.sensitive} sensitive, ${s3.insensitive} insensitive, ${s3.cascade} cascade, ${s3.notApplied} not applied, ${s3.error} error, ${s3.unpaired} unpaired${report2.reason === void 0 ? "" : ` (${report2.reason})`}
|
|
111038
|
+
`${report2.verdict} \u2014 journey '${report2.journeyId}': ${s3.sensitive} sensitive, ${s3.insensitive} insensitive, ${s3.cascade} cascade, ${s3.notApplied} not applied, ${s3.error} error, ${s3.unpaired} unpaired${targeted}${report2.reason === void 0 ? "" : ` (${report2.reason})`}
|
|
110805
111039
|
`
|
|
110806
111040
|
);
|
|
110807
111041
|
}
|
|
@@ -115046,13 +115280,14 @@ var CLI_TOOL_SPECS = [
|
|
|
115046
115280
|
},
|
|
115047
115281
|
{
|
|
115048
115282
|
name: "chain_journeys",
|
|
115049
|
-
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.",
|
|
115283
|
+
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. #608: params supplies explicit producer (discover) params, validated against the producer's schema before anything runs. 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.",
|
|
115050
115284
|
command: {
|
|
115051
115285
|
path: "journey chain",
|
|
115052
115286
|
params: {
|
|
115053
115287
|
from: s2("--from", { required: true }),
|
|
115054
115288
|
to: s2("--to", { required: true }),
|
|
115055
115289
|
requests: path("--requests", { required: true }),
|
|
115290
|
+
params: { kind: "params", flag: "--param" },
|
|
115056
115291
|
storageState: session("--storage-state"),
|
|
115057
115292
|
...EXTENSION,
|
|
115058
115293
|
...EMULATION,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// this plain `tsc --build` dist (no bundler substitution), so it needs real committed values
|
|
6
6
|
// here instead. See ./engine.ts, which prefers the esbuild-injected value when present and
|
|
7
7
|
// falls back to these.
|
|
8
|
-
export const GENERATED_COMMIT = "
|
|
9
|
-
export const GENERATED_TREE = "
|
|
10
|
-
export const GENERATED_BUILT_AT = "2026-10-
|
|
8
|
+
export const GENERATED_COMMIT = "0a3d2f5";
|
|
9
|
+
export const GENERATED_TREE = "963f59f";
|
|
10
|
+
export const GENERATED_BUILT_AT = "2026-10-19T17:40:57.283Z";
|
|
11
11
|
//# sourceMappingURL=build-info.generated.js.map
|
package/dist/journey-api.js
CHANGED
|
@@ -425,7 +425,11 @@ export async function runJourneyProgrammatically(opts, mutation = {}) {
|
|
|
425
425
|
// `extract as: "apiKey"`), so the output, failures and artifacts below never carry it.
|
|
426
426
|
let runSecrets = secrets;
|
|
427
427
|
try {
|
|
428
|
-
|
|
428
|
+
// #609: a mutated copy may no longer name a param the stored Journey takes (a targeted proof
|
|
429
|
+
// relaxed the only check naming an assertion-only `expected_*` param). The supplied set was
|
|
430
|
+
// validated against the stored Journey above; the copy runs with the subset it still reads.
|
|
431
|
+
const replayParams = replayed === journey ? params : prefixParams(journey, replayed, params);
|
|
432
|
+
const raw = await outcomeChecks.run(actor, () => runner.run({ journey: replayed, params: replayParams, policy }));
|
|
429
433
|
runSecrets = runSecretValues(secrets, raw);
|
|
430
434
|
result = redactSecretValues(raw, runSecrets);
|
|
431
435
|
}
|