@jevitate/cli 0.8.0 → 0.10.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/anchor-baselines.d.ts +26 -0
- package/dist/anchor-baselines.js +25 -0
- package/dist/anchor-baselines.js.map +1 -0
- package/dist/approval-provenance.d.ts +48 -2
- package/dist/approval-provenance.js +110 -6
- package/dist/approval-provenance.js.map +1 -1
- package/dist/bin.js +25111 -17835
- package/dist/browser-cli.d.ts +10 -0
- package/dist/browser-cli.js +50 -0
- package/dist/browser-cli.js.map +1 -0
- package/dist/build-info.generated.js +2 -2
- package/dist/catalog-analysis.js +14 -0
- package/dist/catalog-analysis.js.map +1 -1
- package/dist/catalog-api.js +12 -4
- package/dist/catalog-api.js.map +1 -1
- package/dist/catalog-bundle-api.d.ts +73 -0
- package/dist/catalog-bundle-api.js +206 -0
- package/dist/catalog-bundle-api.js.map +1 -0
- package/dist/catalog-bundle-findings.d.ts +54 -0
- package/dist/catalog-bundle-findings.js +252 -0
- package/dist/catalog-bundle-findings.js.map +1 -0
- package/dist/catalog-bundle.d.ts +192 -0
- package/dist/catalog-bundle.js +578 -0
- package/dist/catalog-bundle.js.map +1 -0
- package/dist/catalog-cli.d.ts +6 -0
- package/dist/catalog-cli.js +180 -5
- package/dist/catalog-cli.js.map +1 -1
- package/dist/catalog-refs.d.ts +42 -0
- package/dist/catalog-refs.js +188 -0
- package/dist/catalog-refs.js.map +1 -0
- package/dist/catalog-review.d.ts +3 -1
- package/dist/catalog-review.js +61 -0
- package/dist/catalog-review.js.map +1 -1
- package/dist/catalog.d.ts +27 -3
- package/dist/catalog.js +46 -2
- package/dist/catalog.js.map +1 -1
- package/dist/change-context.d.ts +44 -0
- package/dist/change-context.js +203 -0
- package/dist/change-context.js.map +1 -0
- package/dist/check-api.d.ts +1 -1
- package/dist/check-api.js +206 -16
- package/dist/check-api.js.map +1 -1
- package/dist/check-cli.d.ts +2 -1
- package/dist/check-cli.js +117 -8
- package/dist/check-cli.js.map +1 -1
- package/dist/check-execute.d.ts +28 -1
- package/dist/check-execute.js +110 -27
- package/dist/check-execute.js.map +1 -1
- package/dist/check-plan.d.ts +14 -0
- package/dist/check-plan.js +24 -1
- package/dist/check-plan.js.map +1 -1
- package/dist/check-types.d.ts +137 -5
- package/dist/check-types.js +8 -0
- package/dist/check-types.js.map +1 -1
- package/dist/cli-output.d.ts +6 -0
- package/dist/cli-output.js +26 -1
- package/dist/cli-output.js.map +1 -1
- package/dist/cli-shared.d.ts +10 -0
- package/dist/cli-shared.js +0 -4
- package/dist/cli-shared.js.map +1 -1
- package/dist/exit-codes.d.ts +6 -3
- package/dist/exit-codes.js +24 -3
- package/dist/exit-codes.js.map +1 -1
- package/dist/explore-adversarial.js +2 -2
- package/dist/explore-adversarial.js.map +1 -1
- package/dist/explore-cli.js +3 -2
- package/dist/explore-cli.js.map +1 -1
- package/dist/explore-coverage.js +3 -3
- package/dist/explore-coverage.js.map +1 -1
- package/dist/explore-feature.js +3 -3
- package/dist/explore-feature.js.map +1 -1
- package/dist/explore-goal.js +11 -5
- package/dist/explore-goal.js.map +1 -1
- package/dist/findings-filing.d.ts +6 -0
- package/dist/findings-filing.js +15 -1
- package/dist/findings-filing.js.map +1 -1
- package/dist/forge-verify.d.ts +224 -0
- package/dist/forge-verify.js +649 -0
- package/dist/forge-verify.js.map +1 -0
- package/dist/heal-probe-guard.d.ts +9 -0
- package/dist/heal-probe-guard.js +113 -0
- package/dist/heal-probe-guard.js.map +1 -0
- package/dist/host-health-run.d.ts +32 -1
- package/dist/host-health-run.js +38 -1
- package/dist/host-health-run.js.map +1 -1
- package/dist/init-codeowners.d.ts +19 -0
- package/dist/init-codeowners.js +66 -0
- package/dist/init-codeowners.js.map +1 -1
- package/dist/job-draft-api.d.ts +52 -0
- package/dist/job-draft-api.js +110 -0
- package/dist/job-draft-api.js.map +1 -0
- package/dist/journeeze-api.d.ts +71 -0
- package/dist/journeeze-api.js +285 -0
- package/dist/journeeze-api.js.map +1 -0
- package/dist/journeeze-connect.d.ts +156 -0
- package/dist/journeeze-connect.js +357 -0
- package/dist/journeeze-connect.js.map +1 -0
- package/dist/journey-anchor-gate.d.ts +52 -0
- package/dist/journey-anchor-gate.js +101 -0
- package/dist/journey-anchor-gate.js.map +1 -0
- package/dist/journey-api.d.ts +43 -3
- package/dist/journey-api.js +226 -21
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.js +162 -20
- package/dist/journey-cli.js.map +1 -1
- package/dist/journey-heal.d.ts +74 -0
- package/dist/journey-heal.js +180 -0
- package/dist/journey-heal.js.map +1 -0
- package/dist/journey-lint-sarif.d.ts +3 -2
- package/dist/journey-lint-sarif.js +9 -2
- package/dist/journey-lint-sarif.js.map +1 -1
- package/dist/journey-migrate-api.d.ts +54 -0
- package/dist/journey-migrate-api.js +64 -0
- package/dist/journey-migrate-api.js.map +1 -0
- package/dist/journey-network-checks.d.ts +5 -1
- package/dist/journey-network-checks.js +15 -4
- package/dist/journey-network-checks.js.map +1 -1
- package/dist/journey-prefix.js +2 -2
- package/dist/journey-prefix.js.map +1 -1
- package/dist/journey-proposal-store.d.ts +109 -0
- package/dist/journey-proposal-store.js +365 -0
- package/dist/journey-proposal-store.js.map +1 -0
- package/dist/journey-result-record.d.ts +42 -0
- package/dist/journey-result-record.js +33 -0
- package/dist/journey-result-record.js.map +1 -0
- package/dist/journey-review-api.js +16 -1
- package/dist/journey-review-api.js.map +1 -1
- package/dist/journey-review.d.ts +18 -1
- package/dist/journey-review.js +116 -5
- package/dist/journey-review.js.map +1 -1
- package/dist/journey-stale-api.d.ts +40 -0
- package/dist/journey-stale-api.js +57 -0
- package/dist/journey-stale-api.js.map +1 -0
- package/dist/launch-armed.js +5 -1
- package/dist/launch-armed.js.map +1 -1
- package/dist/locator-health-api.d.ts +101 -0
- package/dist/locator-health-api.js +203 -0
- package/dist/locator-health-api.js.map +1 -0
- package/dist/locator-health.d.ts +195 -0
- package/dist/locator-health.js +419 -0
- package/dist/locator-health.js.map +1 -0
- package/dist/login-cli.d.ts +2 -0
- package/dist/login-cli.js +56 -11
- package/dist/login-cli.js.map +1 -1
- package/dist/mcp-api.d.ts +5 -1
- package/dist/mcp-api.js +53 -8
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-cli-tools.d.ts +3 -1
- package/dist/mcp-cli-tools.js +80 -10
- package/dist/mcp-cli-tools.js.map +1 -1
- package/dist/multi-run.d.ts +7 -6
- package/dist/multi-run.js +5 -4
- package/dist/multi-run.js.map +1 -1
- package/dist/persona-login.d.ts +60 -3
- package/dist/persona-login.js +341 -31
- package/dist/persona-login.js.map +1 -1
- package/dist/program.js +2 -0
- package/dist/program.js.map +1 -1
- package/dist/project-config.d.ts +29 -0
- package/dist/project-config.js +76 -0
- package/dist/project-config.js.map +1 -0
- package/dist/report-api.d.ts +1 -0
- package/dist/report-api.js +1 -0
- package/dist/report-api.js.map +1 -1
- package/dist/resource-preflight.js +5 -3
- package/dist/resource-preflight.js.map +1 -1
- package/dist/run-metadata.d.ts +5 -2
- package/dist/run-metadata.js +10 -3
- package/dist/run-metadata.js.map +1 -1
- package/dist/run-tags-cli.d.ts +2 -0
- package/dist/run-tags-cli.js +8 -2
- package/dist/run-tags-cli.js.map +1 -1
- package/dist/self-heal-adapter.d.ts +43 -27
- package/dist/self-heal-adapter.js +196 -62
- package/dist/self-heal-adapter.js.map +1 -1
- package/dist/source-cli.js +5 -3
- package/dist/source-cli.js.map +1 -1
- package/dist/suite-explore-options.js +1 -0
- package/dist/suite-explore-options.js.map +1 -1
- package/dist/sweep-api.d.ts +23 -0
- package/dist/sweep-api.js +39 -8
- package/dist/sweep-api.js.map +1 -1
- package/dist/sweep-cli.js +3 -1
- package/dist/sweep-cli.js.map +1 -1
- package/dist/ux-usability.js +3 -2
- package/dist/ux-usability.js.map +1 -1
- package/package.json +17 -15
- package/skills/jevitate-ci-check/SKILL.md +25 -1
- package/skills/jevitate-getting-started/SKILL.md +9 -3
- package/skills/jevitate-mission-scope/SKILL.md +2 -2
- package/skills/jevitate-run-journey/SKILL.md +36 -5
- package/skills/jevitate-test-campaign/SKILL.md +13 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { type ApprovalProvenance, type Journey, type JourneyProposal } from "@jevitate/journey";
|
|
2
|
+
import { type HealAttempt, type ProposedRevisionDraft } from "@jevitate/runtime";
|
|
3
|
+
import type { Recording } from "@jevitate/recording";
|
|
4
|
+
/**
|
|
5
|
+
* #453 — proposed Journey revisions, beside the journeys directory (`.proposals/`, committed with
|
|
6
|
+
* the PR like `.approved/`; a dot-folder, so never listed as a Journey). One PENDING proposal per
|
|
7
|
+
* Journey, keyed by the Journey id: `.proposals/<id>.json`; a newer one replaces it. A rejected one
|
|
8
|
+
* moves to `.proposals/<id>.rejected/<proposalId>.json` with who rejected it and why. A run never
|
|
9
|
+
* writes the stored Journey — only `journey promote --proposal` does.
|
|
10
|
+
*
|
|
11
|
+
* Nothing here can hold a secret: step values arrive through `sanitizeStep` (hidden), every string
|
|
12
|
+
* passes the redaction of the run's secret values, and the recording is the Journey's own. The free
|
|
13
|
+
* text (hypotheses, evidence, notes, rejection details, paths) is also scrubbed of credential-shaped
|
|
14
|
+
* values and sensitive URL parameters. It DOES hold control labels and change evidence — the files
|
|
15
|
+
* are committed (docs/journeys.md).
|
|
16
|
+
*
|
|
17
|
+
* #453 review: the store never follows a symlink — the `.proposals/` directories and files are
|
|
18
|
+
* `lstat`ed on read and write and a link is refused (`JourneyProposalInvalidError`); a write goes
|
|
19
|
+
* to a temporary file renamed into place (atomic).
|
|
20
|
+
*/
|
|
21
|
+
/** No pending proposal with that id (or none at all). Exit 64. */
|
|
22
|
+
export declare class JourneyProposalNotFoundError extends Error {
|
|
23
|
+
readonly code = "E_JOURNEY_PROPOSAL_NOT_FOUND";
|
|
24
|
+
}
|
|
25
|
+
/** The proposal was made against a Journey that has changed since, or its proof fields were touched. Exit 64. */
|
|
26
|
+
export declare class JourneyProposalStaleError extends Error {
|
|
27
|
+
readonly code = "E_JOURNEY_PROPOSAL_STALE";
|
|
28
|
+
}
|
|
29
|
+
/** A proposal that changes more than retargets (an assertion, a wait, a request check…) — refused. */
|
|
30
|
+
export declare class JourneyProposalProofError extends Error {
|
|
31
|
+
readonly code = "E_JOURNEY_PROPOSAL_PROOF";
|
|
32
|
+
}
|
|
33
|
+
/** A proposal file that is not valid. */
|
|
34
|
+
export declare class JourneyProposalInvalidError extends Error {
|
|
35
|
+
readonly code = "E_JOURNEY_PROPOSAL_INVALID";
|
|
36
|
+
}
|
|
37
|
+
/** True for a well-formed proposal id (12 hex characters) — also what keeps `../x` out of every path. */
|
|
38
|
+
export declare function isProposalId(id: string): boolean;
|
|
39
|
+
export declare function proposalPath(journeysDir: string, journeyId: string): string;
|
|
40
|
+
export declare function rejectedProposalPath(journeysDir: string, journeyId: string, proposalId: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* #453 review: re-runs the heal floor on every step a revision changes (on write, on read for review
|
|
43
|
+
* and on accept) — a proposal file edited by hand, or written by an older build, never lets
|
|
44
|
+
* `journey promote --proposal` store what the runner would not have healed:
|
|
45
|
+
* - the floor (`healFloor` with the built-in `SafetyPolicy` classification, `journeyStepRisk`) holds
|
|
46
|
+
* for the step before AND after: never a proof / write / risky-control step;
|
|
47
|
+
* - a retargeted click/fill expects only GET/HEAD/OPTIONS requests (part of the floor);
|
|
48
|
+
* - a retargeted navigate URL stays on the Journey's allowed origin (its recorded site).
|
|
49
|
+
*/
|
|
50
|
+
export declare function proposalFloorViolation(stored: Journey, proposed: Recording): string | null;
|
|
51
|
+
/**
|
|
52
|
+
* #467: a proposal names each changed step by its flat index AND, when the step has one, its stable
|
|
53
|
+
* id — refused when they disagree (the index points at a different step than the one that was healed,
|
|
54
|
+
* or the file was edited). Null when every named id is the stored step's at that index.
|
|
55
|
+
*/
|
|
56
|
+
export declare function proposalStepIdViolation(stored: Journey, steps: readonly {
|
|
57
|
+
readonly index: number;
|
|
58
|
+
readonly stepId?: string;
|
|
59
|
+
}[]): string | null;
|
|
60
|
+
export interface WriteJourneyProposalInput {
|
|
61
|
+
readonly journeyId: string;
|
|
62
|
+
/** The stored Journey the revision was made against. */
|
|
63
|
+
readonly base: Journey;
|
|
64
|
+
readonly draft: ProposedRevisionDraft;
|
|
65
|
+
readonly attempts: readonly HealAttempt[];
|
|
66
|
+
readonly changes: {
|
|
67
|
+
readonly range?: string;
|
|
68
|
+
readonly baseSha?: string;
|
|
69
|
+
readonly headSha?: string;
|
|
70
|
+
readonly notes?: readonly string[];
|
|
71
|
+
};
|
|
72
|
+
readonly runResultPath?: string;
|
|
73
|
+
/** Secret values of the run, scrubbed from every string written. */
|
|
74
|
+
readonly secrets?: readonly string[];
|
|
75
|
+
}
|
|
76
|
+
export interface WrittenJourneyProposal {
|
|
77
|
+
readonly proposalId: string;
|
|
78
|
+
readonly path: string;
|
|
79
|
+
/** The id of a pending proposal this one replaced. */
|
|
80
|
+
readonly supersededProposal?: string;
|
|
81
|
+
}
|
|
82
|
+
/** The Journey as it would be stored on accept: the stored one with the proposed recording. */
|
|
83
|
+
export declare function proposedJourney(stored: Journey, proposal: Pick<JourneyProposal, "recording">): Journey;
|
|
84
|
+
/**
|
|
85
|
+
* Writes the proposal for `journeyId`, replacing a pending one. Refused (`JourneyProposalProofError`)
|
|
86
|
+
* when the revision changes anything but retargets (`assertRecordingProofUntouched`).
|
|
87
|
+
*/
|
|
88
|
+
export declare function writeJourneyProposal(journeysDir: string, input: WriteJourneyProposalInput): Promise<WrittenJourneyProposal>;
|
|
89
|
+
/** The pending proposal for a Journey, or null. An unreadable or invalid file is refused, never ignored. */
|
|
90
|
+
export declare function readJourneyProposal(journeysDir: string, journeyId: string): Promise<JourneyProposal | null>;
|
|
91
|
+
/** The pending proposal named `proposalId` for the Journey; `JourneyProposalNotFoundError` when none matches. */
|
|
92
|
+
export declare function requireJourneyProposal(journeysDir: string, journeyId: string, proposalId: string): Promise<JourneyProposal>;
|
|
93
|
+
/** True when the proposal was made against a different Journey than the stored one. */
|
|
94
|
+
export declare function isProposalStale(stored: Journey, proposal: JourneyProposal): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Re-checks a proposal against the stored Journey (on read for review and again on accept): stale
|
|
97
|
+
* when the Journey changed since, proof-touched when the file was edited to change anything but
|
|
98
|
+
* retargets, or when its hash no longer matches its recording.
|
|
99
|
+
*/
|
|
100
|
+
export declare function checkProposal(stored: Journey, proposal: JourneyProposal): JourneyProposalStaleError | JourneyProposalProofError | null;
|
|
101
|
+
/** Deletes the pending proposal (after it was accepted). */
|
|
102
|
+
export declare function deleteJourneyProposal(journeysDir: string, journeyId: string): Promise<void>;
|
|
103
|
+
/** Moves the pending proposal to `.rejected/`, recording when, why and how it was rejected. */
|
|
104
|
+
export declare function rejectJourneyProposal(journeysDir: string, journeyId: string, proposalId: string, rejection: {
|
|
105
|
+
readonly reason: string;
|
|
106
|
+
readonly provenance: ApprovalProvenance;
|
|
107
|
+
}): Promise<{
|
|
108
|
+
path: string;
|
|
109
|
+
}>;
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { lstat, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, relative, sep } from "node:path";
|
|
3
|
+
import { contentHash, clock } from "@jevitate/domain";
|
|
4
|
+
import { JourneyProposalSchema, RejectedProposalSchema, } from "@jevitate/journey";
|
|
5
|
+
import { assertRecordingProofUntouched, flattenRecording, healFloor, sanitizeStep } from "@jevitate/runtime";
|
|
6
|
+
import { journeyReviewHash } from "./journey-review.js";
|
|
7
|
+
import { journeyStepRisk } from "./journey-heal.js";
|
|
8
|
+
import { redactCredentialShapes, redactText, redactUrl } from "@jevitate/ai-core";
|
|
9
|
+
/**
|
|
10
|
+
* #453 — proposed Journey revisions, beside the journeys directory (`.proposals/`, committed with
|
|
11
|
+
* the PR like `.approved/`; a dot-folder, so never listed as a Journey). One PENDING proposal per
|
|
12
|
+
* Journey, keyed by the Journey id: `.proposals/<id>.json`; a newer one replaces it. A rejected one
|
|
13
|
+
* moves to `.proposals/<id>.rejected/<proposalId>.json` with who rejected it and why. A run never
|
|
14
|
+
* writes the stored Journey — only `journey promote --proposal` does.
|
|
15
|
+
*
|
|
16
|
+
* Nothing here can hold a secret: step values arrive through `sanitizeStep` (hidden), every string
|
|
17
|
+
* passes the redaction of the run's secret values, and the recording is the Journey's own. The free
|
|
18
|
+
* text (hypotheses, evidence, notes, rejection details, paths) is also scrubbed of credential-shaped
|
|
19
|
+
* values and sensitive URL parameters. It DOES hold control labels and change evidence — the files
|
|
20
|
+
* are committed (docs/journeys.md).
|
|
21
|
+
*
|
|
22
|
+
* #453 review: the store never follows a symlink — the `.proposals/` directories and files are
|
|
23
|
+
* `lstat`ed on read and write and a link is refused (`JourneyProposalInvalidError`); a write goes
|
|
24
|
+
* to a temporary file renamed into place (atomic).
|
|
25
|
+
*/
|
|
26
|
+
/** No pending proposal with that id (or none at all). Exit 64. */
|
|
27
|
+
export class JourneyProposalNotFoundError extends Error {
|
|
28
|
+
code = "E_JOURNEY_PROPOSAL_NOT_FOUND";
|
|
29
|
+
}
|
|
30
|
+
/** The proposal was made against a Journey that has changed since, or its proof fields were touched. Exit 64. */
|
|
31
|
+
export class JourneyProposalStaleError extends Error {
|
|
32
|
+
code = "E_JOURNEY_PROPOSAL_STALE";
|
|
33
|
+
}
|
|
34
|
+
/** A proposal that changes more than retargets (an assertion, a wait, a request check…) — refused. */
|
|
35
|
+
export class JourneyProposalProofError extends Error {
|
|
36
|
+
code = "E_JOURNEY_PROPOSAL_PROOF";
|
|
37
|
+
}
|
|
38
|
+
/** A proposal file that is not valid. */
|
|
39
|
+
export class JourneyProposalInvalidError extends Error {
|
|
40
|
+
code = "E_JOURNEY_PROPOSAL_INVALID";
|
|
41
|
+
}
|
|
42
|
+
const PROPOSAL_ID = /^[0-9a-f]{12}$/;
|
|
43
|
+
/** True for a well-formed proposal id (12 hex characters) — also what keeps `../x` out of every path. */
|
|
44
|
+
export function isProposalId(id) {
|
|
45
|
+
return PROPOSAL_ID.test(id);
|
|
46
|
+
}
|
|
47
|
+
function parts(id) {
|
|
48
|
+
const p = id.split("/");
|
|
49
|
+
return { dir: p.slice(0, -1), base: p[p.length - 1] ?? id };
|
|
50
|
+
}
|
|
51
|
+
export function proposalPath(journeysDir, journeyId) {
|
|
52
|
+
const { dir, base } = parts(journeyId);
|
|
53
|
+
return join(journeysDir, ".proposals", ...dir, `${base}.json`);
|
|
54
|
+
}
|
|
55
|
+
export function rejectedProposalPath(journeysDir, journeyId, proposalId) {
|
|
56
|
+
const { dir, base } = parts(journeyId);
|
|
57
|
+
return join(journeysDir, ".proposals", ...dir, `${base}.rejected`, `${proposalId}.json`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Refuses (`JourneyProposalInvalidError`) when `.proposals/` or any directory or file on the way to
|
|
61
|
+
* `path` under it is a symbolic link — never followed, for a read or a write. Components that do not
|
|
62
|
+
* exist yet are fine (a write creates them).
|
|
63
|
+
*/
|
|
64
|
+
async function assertNoSymlink(path) {
|
|
65
|
+
const marker = `${sep}.proposals${sep}`;
|
|
66
|
+
const at = path.lastIndexOf(marker);
|
|
67
|
+
if (at < 0)
|
|
68
|
+
throw new JourneyProposalInvalidError(`${path} is not under a .proposals directory`);
|
|
69
|
+
const root = path.slice(0, at + marker.length - 1);
|
|
70
|
+
const parts = relative(root, path).split(sep).filter((p) => p !== "");
|
|
71
|
+
let cur = root;
|
|
72
|
+
for (const next of [null, ...parts]) {
|
|
73
|
+
if (next !== null)
|
|
74
|
+
cur = join(cur, next);
|
|
75
|
+
let st;
|
|
76
|
+
try {
|
|
77
|
+
st = await lstat(cur);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
if (typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT")
|
|
81
|
+
return;
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
if (st.isSymbolicLink())
|
|
85
|
+
throw new JourneyProposalInvalidError(`refusing to follow a symbolic link at ${cur} — proposals are never read or written through a link`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function readJson(path) {
|
|
89
|
+
await assertNoSymlink(path);
|
|
90
|
+
let raw;
|
|
91
|
+
try {
|
|
92
|
+
raw = await readFile(path, "utf8");
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
if (typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT")
|
|
96
|
+
return null;
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
return JSON.parse(raw);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
throw new JourneyProposalInvalidError(`${path} is not valid JSON`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function writeJson(path, value) {
|
|
107
|
+
await assertNoSymlink(path);
|
|
108
|
+
await mkdir(dirname(path), { recursive: true });
|
|
109
|
+
await assertNoSymlink(path);
|
|
110
|
+
const tmp = `${path}.${process.pid}.${clock.monotonicMs().toString(36)}.tmp`;
|
|
111
|
+
await writeFile(tmp, `${JSON.stringify(value, null, 2)}\n`, { flag: "wx" });
|
|
112
|
+
try {
|
|
113
|
+
await rename(tmp, path);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
await rm(tmp, { force: true });
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function removeFile(path) {
|
|
121
|
+
await assertNoSymlink(path);
|
|
122
|
+
await rm(path, { force: true });
|
|
123
|
+
}
|
|
124
|
+
/** Deterministic JSON (keys sorted, undefined dropped): two steps are the same when these agree. */
|
|
125
|
+
function canonical(v) {
|
|
126
|
+
if (Array.isArray(v))
|
|
127
|
+
return `[${v.map(canonical).join(",")}]`;
|
|
128
|
+
if (v !== null && typeof v === "object") {
|
|
129
|
+
const o = v;
|
|
130
|
+
return `{${Object.keys(o)
|
|
131
|
+
.filter((k) => o[k] !== undefined)
|
|
132
|
+
.sort()
|
|
133
|
+
.map((k) => `${JSON.stringify(k)}:${canonical(o[k])}`)
|
|
134
|
+
.join(",")}}`;
|
|
135
|
+
}
|
|
136
|
+
return JSON.stringify(v) ?? "undefined";
|
|
137
|
+
}
|
|
138
|
+
function originOf(url) {
|
|
139
|
+
if (!/^[a-z][a-z0-9+.-]*:/i.test(url))
|
|
140
|
+
return null;
|
|
141
|
+
try {
|
|
142
|
+
return new URL(url).origin;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return "invalid";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* #453 review: re-runs the heal floor on every step a revision changes (on write, on read for review
|
|
150
|
+
* and on accept) — a proposal file edited by hand, or written by an older build, never lets
|
|
151
|
+
* `journey promote --proposal` store what the runner would not have healed:
|
|
152
|
+
* - the floor (`healFloor` with the built-in `SafetyPolicy` classification, `journeyStepRisk`) holds
|
|
153
|
+
* for the step before AND after: never a proof / write / risky-control step;
|
|
154
|
+
* - a retargeted click/fill expects only GET/HEAD/OPTIONS requests (part of the floor);
|
|
155
|
+
* - a retargeted navigate URL stays on the Journey's allowed origin (its recorded site).
|
|
156
|
+
*/
|
|
157
|
+
export function proposalFloorViolation(stored, proposed) {
|
|
158
|
+
const riskOf = journeyStepRisk();
|
|
159
|
+
const before = flattenRecording(stored.recording);
|
|
160
|
+
const after = flattenRecording(proposed);
|
|
161
|
+
let site = null;
|
|
162
|
+
try {
|
|
163
|
+
site = new URL(stored.recording.site).origin;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
site = null;
|
|
167
|
+
}
|
|
168
|
+
for (let i = 0; i < after.length; i++) {
|
|
169
|
+
const b = before[i];
|
|
170
|
+
const a = after[i];
|
|
171
|
+
if (b !== undefined && canonical(b.step) === canonical(a.step))
|
|
172
|
+
continue;
|
|
173
|
+
for (const [which, rec] of [["before", b?.recorded], ["after", a.recorded]]) {
|
|
174
|
+
if (rec === undefined)
|
|
175
|
+
return `step ${i + 1} is not in the stored Journey`;
|
|
176
|
+
const floor = healFloor(rec, riskOf);
|
|
177
|
+
if (floor.floor !== "healable")
|
|
178
|
+
return `step ${i + 1} (${which}): ${floor.reason}`;
|
|
179
|
+
}
|
|
180
|
+
if (a.step.kind === "navigate") {
|
|
181
|
+
const o = originOf(a.step.url);
|
|
182
|
+
if (o !== null && o !== site)
|
|
183
|
+
return `step ${i + 1}: the retargeted URL is on ${o}, not the Journey's origin ${site ?? "(none)"}`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* #467: a proposal names each changed step by its flat index AND, when the step has one, its stable
|
|
190
|
+
* id — refused when they disagree (the index points at a different step than the one that was healed,
|
|
191
|
+
* or the file was edited). Null when every named id is the stored step's at that index.
|
|
192
|
+
*/
|
|
193
|
+
export function proposalStepIdViolation(stored, steps) {
|
|
194
|
+
const flat = flattenRecording(stored.recording);
|
|
195
|
+
for (const s of steps) {
|
|
196
|
+
if (s.stepId === undefined)
|
|
197
|
+
continue;
|
|
198
|
+
const have = flat[s.index]?.recorded.stepId;
|
|
199
|
+
if (have !== s.stepId)
|
|
200
|
+
return `step ${s.index + 1} is named ${s.stepId}, but the Journey's step ${s.index + 1} is ${have ?? "(no id)"}`;
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
/** The Journey as it would be stored on accept: the stored one with the proposed recording. */
|
|
205
|
+
export function proposedJourney(stored, proposal) {
|
|
206
|
+
return { ...stored, recording: proposal.recording };
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Writes the proposal for `journeyId`, replacing a pending one. Refused (`JourneyProposalProofError`)
|
|
210
|
+
* when the revision changes anything but retargets (`assertRecordingProofUntouched`).
|
|
211
|
+
*/
|
|
212
|
+
export async function writeJourneyProposal(journeysDir, input) {
|
|
213
|
+
const violation = assertRecordingProofUntouched(input.base.recording, input.draft.recording);
|
|
214
|
+
if (violation !== null)
|
|
215
|
+
throw new JourneyProposalProofError(`refusing to store a proposal that touches the Journey's proof (${violation.code}): ${violation.detail}`);
|
|
216
|
+
const floor = proposalFloorViolation(input.base, input.draft.recording);
|
|
217
|
+
if (floor !== null)
|
|
218
|
+
throw new JourneyProposalProofError(`refusing to store a proposal the heal floor refuses: ${floor}`);
|
|
219
|
+
const idClash = proposalStepIdViolation(input.base, input.draft.steps);
|
|
220
|
+
if (idClash !== null)
|
|
221
|
+
throw new JourneyProposalProofError(`refusing to store a proposal whose step ids disagree with the Journey: ${idClash}`);
|
|
222
|
+
const baseHash = journeyReviewHash(input.base);
|
|
223
|
+
const secrets = [...(input.secrets ?? [])];
|
|
224
|
+
// Every string: the run's secret values. Free text (not the recording or a step): also
|
|
225
|
+
// credential-shaped values and sensitive URL parameters (#453 review).
|
|
226
|
+
const scrub = (v, free = true) => typeof v === "string"
|
|
227
|
+
? free
|
|
228
|
+
? redactUrl(redactCredentialShapes(secrets.length === 0 ? v : redactText(v, secrets)))
|
|
229
|
+
: secrets.length === 0
|
|
230
|
+
? v
|
|
231
|
+
: redactText(v, secrets)
|
|
232
|
+
: Array.isArray(v)
|
|
233
|
+
? v.map((x) => scrub(x, free))
|
|
234
|
+
: v !== null && typeof v === "object"
|
|
235
|
+
? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, scrub(x, free)]))
|
|
236
|
+
: v;
|
|
237
|
+
const screenshotOf = (n) => input.attempts.find((a) => a.n === n)?.observation?.screenshot;
|
|
238
|
+
const steps = input.draft.steps.map((s) => {
|
|
239
|
+
const shot = screenshotOf(s.attempt);
|
|
240
|
+
const before = s.evidence[0]?.before;
|
|
241
|
+
const after = s.evidence[0]?.after;
|
|
242
|
+
return {
|
|
243
|
+
index: s.index,
|
|
244
|
+
...(s.stepId === undefined ? {} : { stepId: s.stepId }),
|
|
245
|
+
before: sanitizeStep(s.before),
|
|
246
|
+
after: sanitizeStep(s.after),
|
|
247
|
+
justification: {
|
|
248
|
+
hypothesis: s.hypothesis,
|
|
249
|
+
evidence: [...s.evidence],
|
|
250
|
+
...(s.anchorNotInChange === true ? { anchorNotInChange: true } : {}),
|
|
251
|
+
},
|
|
252
|
+
evidence: { ...(before === undefined ? {} : { before }), ...(after === undefined ? {} : { after }) },
|
|
253
|
+
...(shot === undefined ? {} : { screenshots: [shot] }),
|
|
254
|
+
};
|
|
255
|
+
});
|
|
256
|
+
const proposalId = contentHash({ baseHash, steps: steps.map((s) => ({ index: s.index, after: s.after })) }).slice(0, 12);
|
|
257
|
+
const proposed = proposedJourney(input.base, { recording: input.draft.recording });
|
|
258
|
+
const body = {
|
|
259
|
+
v: 1,
|
|
260
|
+
kind: "journey-proposal",
|
|
261
|
+
proposalId,
|
|
262
|
+
journeyId: input.journeyId,
|
|
263
|
+
baseHash,
|
|
264
|
+
proposedHash: journeyReviewHash(proposed),
|
|
265
|
+
createdAt: clock.nowIso(),
|
|
266
|
+
recording: input.draft.recording,
|
|
267
|
+
steps,
|
|
268
|
+
changes: {
|
|
269
|
+
...(input.changes.range === undefined ? {} : { range: input.changes.range }),
|
|
270
|
+
...(input.changes.baseSha === undefined ? {} : { baseSha: input.changes.baseSha }),
|
|
271
|
+
...(input.changes.headSha === undefined ? {} : { headSha: input.changes.headSha }),
|
|
272
|
+
notes: [...(input.changes.notes ?? [])],
|
|
273
|
+
},
|
|
274
|
+
attempts: input.attempts.map((a) => ({ ...a, candidate: a.candidate === null ? null : sanitizeStep(a.candidate) })),
|
|
275
|
+
run: input.runResultPath === undefined ? {} : { resultPath: input.runResultPath },
|
|
276
|
+
};
|
|
277
|
+
const plain = JSON.parse(JSON.stringify(body));
|
|
278
|
+
const strict = scrub(plain, false);
|
|
279
|
+
const free = scrub(plain, true);
|
|
280
|
+
const scrubbed = {
|
|
281
|
+
...free,
|
|
282
|
+
...Object.fromEntries(["v", "kind", "proposalId", "journeyId", "baseHash", "proposedHash", "createdAt", "recording"].map((k) => [k, strict[k]])),
|
|
283
|
+
steps: free.steps.map((st, i) => ({ ...st, before: strict.steps[i].before, after: strict.steps[i].after })),
|
|
284
|
+
changes: { ...free.changes, ...("baseSha" in strict.changes ? { baseSha: strict.changes.baseSha } : {}), ...("headSha" in strict.changes ? { headSha: strict.changes.headSha } : {}) },
|
|
285
|
+
attempts: free.attempts.map((a, i) => ({ ...a, candidate: strict.attempts[i].candidate })),
|
|
286
|
+
};
|
|
287
|
+
const parsed = JourneyProposalSchema.safeParse(scrubbed);
|
|
288
|
+
if (!parsed.success)
|
|
289
|
+
throw new JourneyProposalInvalidError(`the proposal does not satisfy its schema: ${parsed.error.issues[0]?.path.join(".") ?? ""} ${parsed.error.issues[0]?.message ?? "invalid"}`);
|
|
290
|
+
const path = proposalPath(journeysDir, input.journeyId);
|
|
291
|
+
const previous = await readJourneyProposal(journeysDir, input.journeyId).catch(() => null);
|
|
292
|
+
await writeJson(path, parsed.data);
|
|
293
|
+
return {
|
|
294
|
+
proposalId,
|
|
295
|
+
path,
|
|
296
|
+
...(previous !== null && previous.proposalId !== proposalId ? { supersededProposal: previous.proposalId } : {}),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
/** The pending proposal for a Journey, or null. An unreadable or invalid file is refused, never ignored. */
|
|
300
|
+
export async function readJourneyProposal(journeysDir, journeyId) {
|
|
301
|
+
const path = proposalPath(journeysDir, journeyId);
|
|
302
|
+
const raw = await readJson(path);
|
|
303
|
+
if (raw === null)
|
|
304
|
+
return null;
|
|
305
|
+
const parsed = JourneyProposalSchema.safeParse(raw);
|
|
306
|
+
if (!parsed.success)
|
|
307
|
+
throw new JourneyProposalInvalidError(`${path} is not a valid Journey proposal: ${parsed.error.issues[0]?.message ?? "invalid"}`);
|
|
308
|
+
return parsed.data;
|
|
309
|
+
}
|
|
310
|
+
/** The pending proposal named `proposalId` for the Journey; `JourneyProposalNotFoundError` when none matches. */
|
|
311
|
+
export async function requireJourneyProposal(journeysDir, journeyId, proposalId) {
|
|
312
|
+
const proposal = isProposalId(proposalId) ? await readJourneyProposal(journeysDir, journeyId) : null;
|
|
313
|
+
if (proposal === null || proposal.proposalId !== proposalId || proposal.journeyId !== journeyId) {
|
|
314
|
+
throw new JourneyProposalNotFoundError(`journey '${journeyId}' has no pending proposal '${proposalId}' — see: jevitate journey review ${journeyId}`);
|
|
315
|
+
}
|
|
316
|
+
return proposal;
|
|
317
|
+
}
|
|
318
|
+
/** True when the proposal was made against a different Journey than the stored one. */
|
|
319
|
+
export function isProposalStale(stored, proposal) {
|
|
320
|
+
return journeyReviewHash(stored) !== proposal.baseHash;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Re-checks a proposal against the stored Journey (on read for review and again on accept): stale
|
|
324
|
+
* when the Journey changed since, proof-touched when the file was edited to change anything but
|
|
325
|
+
* retargets, or when its hash no longer matches its recording.
|
|
326
|
+
*/
|
|
327
|
+
export function checkProposal(stored, proposal) {
|
|
328
|
+
if (isProposalStale(stored, proposal)) {
|
|
329
|
+
return new JourneyProposalStaleError(`proposal '${proposal.proposalId}' was made against journey '${stored.metadata.id}' ${proposal.baseHash.slice(0, 8)}, which has changed since (now ${journeyReviewHash(stored).slice(0, 8)}) — re-run the self-heal: jevitate journey run ${stored.metadata.id} --self-heal`);
|
|
330
|
+
}
|
|
331
|
+
const violation = assertRecordingProofUntouched(stored.recording, proposal.recording);
|
|
332
|
+
if (violation !== null)
|
|
333
|
+
return new JourneyProposalProofError(`proposal '${proposal.proposalId}' touches the Journey's proof (${violation.code}): ${violation.detail}`);
|
|
334
|
+
const floor = proposalFloorViolation(stored, proposal.recording);
|
|
335
|
+
if (floor !== null)
|
|
336
|
+
return new JourneyProposalProofError(`proposal '${proposal.proposalId}' changes a step the heal floor refuses: ${floor}`);
|
|
337
|
+
const idClash = proposalStepIdViolation(stored, proposal.steps);
|
|
338
|
+
if (idClash !== null)
|
|
339
|
+
return new JourneyProposalProofError(`proposal '${proposal.proposalId}' names a step by an id the Journey's step does not have: ${idClash}`);
|
|
340
|
+
if (journeyReviewHash(proposedJourney(stored, proposal)) !== proposal.proposedHash) {
|
|
341
|
+
return new JourneyProposalProofError(`proposal '${proposal.proposalId}' does not match its recorded hash — the file was edited`);
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
/** Deletes the pending proposal (after it was accepted). */
|
|
346
|
+
export async function deleteJourneyProposal(journeysDir, journeyId) {
|
|
347
|
+
await removeFile(proposalPath(journeysDir, journeyId));
|
|
348
|
+
}
|
|
349
|
+
/** Moves the pending proposal to `.rejected/`, recording when, why and how it was rejected. */
|
|
350
|
+
export async function rejectJourneyProposal(journeysDir, journeyId, proposalId, rejection) {
|
|
351
|
+
const proposal = await requireJourneyProposal(journeysDir, journeyId, proposalId);
|
|
352
|
+
const record = RejectedProposalSchema.parse({
|
|
353
|
+
v: 1,
|
|
354
|
+
kind: "journey-proposal-rejected",
|
|
355
|
+
rejectedAt: clock.nowIso(),
|
|
356
|
+
reason: rejection.reason,
|
|
357
|
+
provenance: rejection.provenance,
|
|
358
|
+
proposal,
|
|
359
|
+
});
|
|
360
|
+
const path = rejectedProposalPath(journeysDir, journeyId, proposalId);
|
|
361
|
+
await writeJson(path, record);
|
|
362
|
+
await removeFile(proposalPath(journeysDir, journeyId));
|
|
363
|
+
return { path };
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=journey-proposal-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journey-proposal-store.js","sourceRoot":"","sources":["../src/journey-proposal-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type MissionOutcome } from "@jevitate/domain";
|
|
2
|
+
import type { Journey } from "@jevitate/journey";
|
|
3
|
+
import type { HealReport, JourneyRunResult } from "@jevitate/runtime";
|
|
4
|
+
/**
|
|
5
|
+
* #453: the `*.result.json` record of one Journey run — what `jevitate report`, the run index and a
|
|
6
|
+
* `check` suite read. Shared by `runJourneyProgrammatically` (a self-heal run persists it) and,
|
|
7
|
+
* once it switches over, `check`. Every string passes `redactSecretParams`.
|
|
8
|
+
*/
|
|
9
|
+
/** The proposal a `healed-pending-review` run wrote (a person reviews it; the stored Journey is untouched). */
|
|
10
|
+
export interface JourneyResultProposal {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly path: string;
|
|
13
|
+
/** The retargeted steps, 1-based, as the review prints them. */
|
|
14
|
+
readonly steps: readonly {
|
|
15
|
+
readonly number: number;
|
|
16
|
+
readonly before: string;
|
|
17
|
+
readonly after: string;
|
|
18
|
+
}[];
|
|
19
|
+
readonly reviewCommand?: string;
|
|
20
|
+
readonly acceptCommand?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface JourneyResultContext {
|
|
23
|
+
/** The Journey as stored (names the secret params; locates the failing step's page). */
|
|
24
|
+
readonly journey: Journey;
|
|
25
|
+
/** The run's params (secret ones are redacted from the record). */
|
|
26
|
+
readonly params: Readonly<Record<string, string>>;
|
|
27
|
+
readonly startedAt: string;
|
|
28
|
+
readonly engine?: unknown;
|
|
29
|
+
readonly suite?: unknown;
|
|
30
|
+
readonly targetBuild?: unknown;
|
|
31
|
+
readonly proposal?: JourneyResultProposal;
|
|
32
|
+
/** The run's heal report when the result does not already carry it. */
|
|
33
|
+
readonly heal?: HealReport;
|
|
34
|
+
/** #470: the test-id convention for `locatorHealth` (default: the project's config, else data-testid/data-test). */
|
|
35
|
+
readonly testIdAttributes?: readonly string[];
|
|
36
|
+
}
|
|
37
|
+
export interface JourneyResultRecord {
|
|
38
|
+
readonly missionOutcome: MissionOutcome;
|
|
39
|
+
readonly exitCode: number;
|
|
40
|
+
readonly result: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
export declare function journeyResultRecord(r: JourneyRunResult, ctx: JourneyResultContext): JourneyResultRecord;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { JOURNEY_MISSION_OUTCOME, journeyExitCode } from "@jevitate/domain";
|
|
2
|
+
import { redactSecretParams } from "./journey-api.js";
|
|
3
|
+
import { journeyStepUrl } from "./check-plan.js";
|
|
4
|
+
import { runLocatorHealth } from "./locator-health-api.js";
|
|
5
|
+
export function journeyResultRecord(r, ctx) {
|
|
6
|
+
const at = r.outcome === "quarantined" || r.outcome === "heal-exhausted" ? r.at : undefined;
|
|
7
|
+
const url = journeyStepUrl(ctx.journey, at);
|
|
8
|
+
const heal = r.heal ?? ctx.heal;
|
|
9
|
+
// #470: how each step's target resolved, and the run's locator health (advisory; never gates here).
|
|
10
|
+
const locatorHealth = runLocatorHealth(ctx.journey, r.resolved, ...(ctx.testIdAttributes === undefined ? [] : [ctx.testIdAttributes]));
|
|
11
|
+
const record = {
|
|
12
|
+
missionOutcome: JOURNEY_MISSION_OUTCOME[r.outcome],
|
|
13
|
+
exitCode: journeyExitCode(r.outcome),
|
|
14
|
+
result: {
|
|
15
|
+
mode: "journey",
|
|
16
|
+
journeyId: ctx.journey.metadata.id,
|
|
17
|
+
outcome: r.outcome,
|
|
18
|
+
...(r.outcome === "quarantined" || r.outcome === "heal-exhausted" ? { reason: r.reason, ...(r.at === undefined ? {} : { at: r.at }) } : {}),
|
|
19
|
+
...(url === undefined ? {} : { url }),
|
|
20
|
+
...(heal === undefined ? {} : { heal }),
|
|
21
|
+
...(ctx.proposal === undefined ? {} : { proposal: ctx.proposal }),
|
|
22
|
+
startedAt: ctx.startedAt,
|
|
23
|
+
target: { seedUrl: ctx.journey.recording.site, allowlist: [new URL(ctx.journey.recording.site).origin] },
|
|
24
|
+
...(ctx.engine === undefined ? {} : { engine: ctx.engine }),
|
|
25
|
+
...(ctx.suite === undefined ? {} : { suite: ctx.suite }),
|
|
26
|
+
...(ctx.targetBuild === undefined ? {} : { targetBuild: ctx.targetBuild }),
|
|
27
|
+
...(r.resolved === undefined ? {} : { resolved: r.resolved }),
|
|
28
|
+
...(locatorHealth === undefined ? {} : { locatorHealth }),
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
return redactSecretParams(record, ctx.journey, ctx.params);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=journey-result-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journey-result-record.js","sourceRoot":"","sources":["../src/journey-result-record.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,11 @@ import { loadCatalog, resolveCatalogDir } from "./catalog-api.js";
|
|
|
6
6
|
import { catalogJourney, journeyLinks } from "./catalog.js";
|
|
7
7
|
import { preApprovalFindings } from "./pre-approval.js";
|
|
8
8
|
import { jevLayerOf } from "./jev-advisor.js";
|
|
9
|
+
import { checkProposal, readJourneyProposal } from "./journey-proposal-store.js";
|
|
10
|
+
import { journeyAnchorIssues } from "./journey-anchor-gate.js";
|
|
11
|
+
import { journeyLocatorHealth, testIdAttributesOrDefault } from "./locator-health-api.js";
|
|
12
|
+
import { isStepIdOnlyStale } from "./journey-stale-api.js";
|
|
13
|
+
import { findProjectDir } from "./project-dir.js";
|
|
9
14
|
import { loadTargetsFile, resolveTargetConfig } from "./target-config.js";
|
|
10
15
|
/**
|
|
11
16
|
* #432: loads one Journey and everything its review sheet needs — the targets.json safety config of
|
|
@@ -34,10 +39,20 @@ export async function reviewJourneyById(journeysDir, id, opts = {}) {
|
|
|
34
39
|
...(opts.readiness === true ? { readiness: true } : {}),
|
|
35
40
|
...(opts.jev === undefined ? {} : { jev: opts.jev }),
|
|
36
41
|
});
|
|
42
|
+
// #453: a pending self-heal proposal, re-checked against the stored Journey (stale, or its proof touched).
|
|
43
|
+
const pending = await readJourneyProposal(journeysDir, id);
|
|
44
|
+
const proposalProblem = pending === null ? null : checkProposal(journey, pending);
|
|
45
|
+
const approvedSnapshot = await readApprovedSnapshot(journeysDir, id);
|
|
37
46
|
const review = buildJourneyReview(journey, {
|
|
47
|
+
anchorIssues: await journeyAnchorIssues(journey, { catalogDir: opts.catalogDir === undefined ? resolveCatalogDir(undefined) : opts.catalogDir, journeysDir, catalog }),
|
|
48
|
+
locatorHealth: journeyLocatorHealth(journey, testIdAttributesOrDefault(findProjectDir())),
|
|
49
|
+
stepIdOnly: isStepIdOnlyStale(journey, approvedSnapshot),
|
|
50
|
+
...(pending === null
|
|
51
|
+
? {}
|
|
52
|
+
: { proposal: { proposal: pending, stale: proposalProblem?.code === "E_JOURNEY_PROPOSAL_STALE", ...(proposalProblem === null ? {} : { problem: proposalProblem.message }) } }),
|
|
38
53
|
...(safety === undefined ? {} : { safety }),
|
|
39
54
|
catalog: { links, findings },
|
|
40
|
-
approvedSnapshot
|
|
55
|
+
approvedSnapshot,
|
|
41
56
|
lastVerify: await readVerifyRecord(journeysDir, id),
|
|
42
57
|
});
|
|
43
58
|
// Fail closed: what is emitted always matches the published schema.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journey-review-api.js","sourceRoot":"","sources":["../src/journey-review-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAoC,MAAM,mBAAmB,CAAC;AAC1G,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAuB,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAiB,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,EAAU,EACV,OAAwK,EAAE;IAE1K,MAAM,OAAO,GAAG,MAAM,IAAI,cAAc,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,IAAI;QAAE,MAAM,IAAI,mBAAmB,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;IAC/E,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC;IACnH,oGAAoG;IACpG,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC/H,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE;QAChG,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,QAAQ;QAC/B,OAAO;QACP,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;KACrD,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"journey-review-api.js","sourceRoot":"","sources":["../src/journey-review-api.ts"],"names":[],"mappings":"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"}
|