@jevitate/cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/ai-cli.js +40 -30
- package/dist/ai-cli.js.map +1 -1
- package/dist/author-journey-cli.d.ts +4 -0
- package/dist/author-journey-cli.js +109 -0
- package/dist/author-journey-cli.js.map +1 -0
- package/dist/bin.js +58077 -22454
- package/dist/bin.js.map +1 -1
- package/dist/browser-run-options.d.ts +58 -0
- package/dist/browser-run-options.js +106 -0
- package/dist/browser-run-options.js.map +1 -0
- package/dist/build-info.generated.d.ts +2 -0
- package/dist/build-info.generated.js +10 -0
- package/dist/build-info.generated.js.map +1 -0
- package/dist/check-api.d.ts +5 -0
- package/dist/check-api.js +233 -0
- package/dist/check-api.js.map +1 -0
- package/dist/check-budget.d.ts +26 -0
- package/dist/check-budget.js +89 -0
- package/dist/check-budget.js.map +1 -0
- package/dist/check-cli.d.ts +31 -0
- package/dist/check-cli.js +109 -0
- package/dist/check-cli.js.map +1 -0
- package/dist/check-execute.d.ts +25 -0
- package/dist/check-execute.js +385 -0
- package/dist/check-execute.js.map +1 -0
- package/dist/check-plan.d.ts +113 -0
- package/dist/check-plan.js +448 -0
- package/dist/check-plan.js.map +1 -0
- package/dist/check-suite.d.ts +171 -0
- package/dist/check-suite.js +515 -0
- package/dist/check-suite.js.map +1 -0
- package/dist/check-types.d.ts +181 -0
- package/dist/check-types.js +35 -0
- package/dist/check-types.js.map +1 -0
- package/dist/cli-args.d.ts +26 -0
- package/dist/cli-args.js +50 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-output.d.ts +102 -0
- package/dist/cli-output.js +516 -0
- package/dist/cli-output.js.map +1 -0
- package/dist/cli-reference.d.ts +3 -0
- package/dist/cli-reference.js +81 -0
- package/dist/cli-reference.js.map +1 -0
- package/dist/cli-refusal.d.ts +12 -0
- package/dist/cli-refusal.js +52 -0
- package/dist/cli-refusal.js.map +1 -0
- package/dist/cli-shared.d.ts +330 -0
- package/dist/cli-shared.js +492 -0
- package/dist/cli-shared.js.map +1 -0
- package/dist/cli-surface.d.ts +33 -0
- package/dist/cli-surface.js +48 -0
- package/dist/cli-surface.js.map +1 -0
- package/dist/conversation-options.d.ts +15 -0
- package/dist/conversation-options.js +10 -0
- package/dist/conversation-options.js.map +1 -0
- package/dist/credentials-file.d.ts +15 -0
- package/dist/credentials-file.js +56 -0
- package/dist/credentials-file.js.map +1 -0
- package/dist/data-dir.d.ts +1 -1
- package/dist/data-dir.js +1 -1
- package/dist/defect-evidence.d.ts +141 -0
- package/dist/defect-evidence.js +502 -0
- package/dist/defect-evidence.js.map +1 -0
- package/dist/demo-aspect-api.d.ts +209 -0
- package/dist/demo-aspect-api.js +397 -0
- package/dist/demo-aspect-api.js.map +1 -0
- package/dist/demo-aspect-cli.d.ts +3 -0
- package/dist/demo-aspect-cli.js +241 -0
- package/dist/demo-aspect-cli.js.map +1 -0
- package/dist/demo-capture.d.ts +108 -0
- package/dist/demo-capture.js +438 -0
- package/dist/demo-capture.js.map +1 -0
- package/dist/engine.d.ts +35 -0
- package/dist/engine.js +25 -0
- package/dist/engine.js.map +1 -0
- package/dist/environments.d.ts +155 -0
- package/dist/environments.js +364 -0
- package/dist/environments.js.map +1 -0
- package/dist/exit-codes.d.ts +46 -0
- package/dist/exit-codes.js +91 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/explore-adversarial.d.ts +137 -0
- package/dist/explore-adversarial.js +218 -0
- package/dist/explore-adversarial.js.map +1 -0
- package/dist/explore-api.d.ts +7 -187
- package/dist/explore-api.js +7 -301
- package/dist/explore-api.js.map +1 -1
- package/dist/explore-author.d.ts +79 -0
- package/dist/explore-author.js +86 -0
- package/dist/explore-author.js.map +1 -0
- package/dist/explore-cli.d.ts +7 -0
- package/dist/explore-cli.js +963 -0
- package/dist/explore-cli.js.map +1 -0
- package/dist/explore-coverage.d.ts +158 -0
- package/dist/explore-coverage.js +240 -0
- package/dist/explore-coverage.js.map +1 -0
- package/dist/explore-feature.d.ts +127 -0
- package/dist/explore-feature.js +220 -0
- package/dist/explore-feature.js.map +1 -0
- package/dist/explore-goal.d.ts +253 -0
- package/dist/explore-goal.js +374 -0
- package/dist/explore-goal.js.map +1 -0
- package/dist/explore-shared.d.ts +152 -0
- package/dist/explore-shared.js +129 -0
- package/dist/explore-shared.js.map +1 -0
- package/dist/explore-specs.d.ts +53 -0
- package/dist/explore-specs.js +333 -0
- package/dist/explore-specs.js.map +1 -0
- package/dist/findings-filing.d.ts +64 -0
- package/dist/findings-filing.js +108 -0
- package/dist/findings-filing.js.map +1 -0
- package/dist/fixture-auth.d.ts +52 -0
- package/dist/fixture-auth.js +82 -0
- package/dist/fixture-auth.js.map +1 -0
- package/dist/fixture-cli.d.ts +70 -0
- package/dist/fixture-cli.js +178 -0
- package/dist/fixture-cli.js.map +1 -0
- package/dist/github-issue-filer.d.ts +62 -0
- package/dist/github-issue-filer.js +188 -0
- package/dist/github-issue-filer.js.map +1 -0
- package/dist/host-health-run.d.ts +24 -0
- package/dist/host-health-run.js +27 -0
- package/dist/host-health-run.js.map +1 -0
- package/dist/http-5xx-outcome.d.ts +6 -0
- package/dist/http-5xx-outcome.js +39 -0
- package/dist/http-5xx-outcome.js.map +1 -0
- package/dist/inbox-cli.d.ts +7 -0
- package/dist/inbox-cli.js +197 -0
- package/dist/inbox-cli.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init-cli.d.ts +4 -0
- package/dist/init-cli.js +127 -0
- package/dist/init-cli.js.map +1 -0
- package/dist/init-keys.d.ts +19 -2
- package/dist/init-keys.js +15 -4
- package/dist/init-keys.js.map +1 -1
- package/dist/init-next-steps.d.ts +35 -0
- package/dist/init-next-steps.js +79 -0
- package/dist/init-next-steps.js.map +1 -0
- package/dist/invariants-file.d.ts +34 -0
- package/dist/invariants-file.js +68 -0
- package/dist/invariants-file.js.map +1 -0
- package/dist/invariants-validate.d.ts +30 -0
- package/dist/invariants-validate.js +105 -0
- package/dist/invariants-validate.js.map +1 -0
- package/dist/journey-annotate-api.d.ts +76 -0
- package/dist/journey-annotate-api.js +256 -0
- package/dist/journey-annotate-api.js.map +1 -0
- package/dist/journey-annotate-cli.d.ts +9 -0
- package/dist/journey-annotate-cli.js +179 -0
- package/dist/journey-annotate-cli.js.map +1 -0
- package/dist/journey-api.d.ts +79 -2
- package/dist/journey-api.js +136 -19
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.d.ts +4 -0
- package/dist/journey-cli.js +370 -0
- package/dist/journey-cli.js.map +1 -0
- package/dist/journey-demo-api.d.ts +112 -0
- package/dist/journey-demo-api.js +392 -0
- package/dist/journey-demo-api.js.map +1 -0
- package/dist/journey-demo-cli.d.ts +10 -0
- package/dist/journey-demo-cli.js +155 -0
- package/dist/journey-demo-cli.js.map +1 -0
- package/dist/kill-signal.d.ts +193 -0
- package/dist/kill-signal.js +284 -0
- package/dist/kill-signal.js.map +1 -0
- package/dist/launch-armed.d.ts +37 -0
- package/dist/launch-armed.js +31 -0
- package/dist/launch-armed.js.map +1 -0
- package/dist/ledger-api.d.ts +106 -0
- package/dist/ledger-api.js +237 -0
- package/dist/ledger-api.js.map +1 -0
- package/dist/ledger-cli.d.ts +18 -0
- package/dist/ledger-cli.js +107 -0
- package/dist/ledger-cli.js.map +1 -0
- package/dist/load-api.d.ts +29 -11
- package/dist/load-api.js +23 -15
- package/dist/load-api.js.map +1 -1
- package/dist/load-cli.d.ts +4 -0
- package/dist/load-cli.js +97 -0
- package/dist/load-cli.js.map +1 -0
- package/dist/log-correlation.d.ts +147 -0
- package/dist/log-correlation.js +325 -0
- package/dist/log-correlation.js.map +1 -0
- package/dist/log-lines.d.ts +131 -0
- package/dist/log-lines.js +389 -0
- package/dist/log-lines.js.map +1 -0
- package/dist/log-sources.d.ts +71 -0
- package/dist/log-sources.js +235 -0
- package/dist/log-sources.js.map +1 -0
- package/dist/logs-cli.d.ts +3 -0
- package/dist/logs-cli.js +51 -0
- package/dist/logs-cli.js.map +1 -0
- package/dist/logs-retention.d.ts +28 -0
- package/dist/logs-retention.js +84 -0
- package/dist/logs-retention.js.map +1 -0
- package/dist/mcp-api.d.ts +89 -1
- package/dist/mcp-api.js +472 -18
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-args.d.ts +38 -0
- package/dist/mcp-args.js +131 -0
- package/dist/mcp-args.js.map +1 -0
- package/dist/mcp-cli-bridge.d.ts +34 -0
- package/dist/mcp-cli-bridge.js +62 -0
- package/dist/mcp-cli-bridge.js.map +1 -0
- package/dist/mcp-cli-runner.d.ts +29 -0
- package/dist/mcp-cli-runner.js +44 -0
- package/dist/mcp-cli-runner.js.map +1 -0
- package/dist/mcp-cli-tools.d.ts +125 -0
- package/dist/mcp-cli-tools.js +680 -0
- package/dist/mcp-cli-tools.js.map +1 -0
- package/dist/mcp-paths.d.ts +28 -0
- package/dist/mcp-paths.js +76 -0
- package/dist/mcp-paths.js.map +1 -0
- package/dist/mission-actors.d.ts +40 -0
- package/dist/mission-actors.js +72 -0
- package/dist/mission-actors.js.map +1 -0
- package/dist/mission-api.d.ts +35 -0
- package/dist/mission-api.js +58 -2
- package/dist/mission-api.js.map +1 -1
- package/dist/mission-cli.d.ts +4 -0
- package/dist/mission-cli.js +247 -0
- package/dist/mission-cli.js.map +1 -0
- package/dist/mission-exit.d.ts +22 -0
- package/dist/mission-exit.js +26 -0
- package/dist/mission-exit.js.map +1 -0
- package/dist/mission-fixtures.d.ts +225 -0
- package/dist/mission-fixtures.js +828 -0
- package/dist/mission-fixtures.js.map +1 -0
- package/dist/mission-journal.d.ts +60 -0
- package/dist/mission-journal.js +115 -0
- package/dist/mission-journal.js.map +1 -0
- package/dist/mission-queue-cli.d.ts +10 -0
- package/dist/mission-queue-cli.js +198 -0
- package/dist/mission-queue-cli.js.map +1 -0
- package/dist/mission-queue-runner.d.ts +126 -0
- package/dist/mission-queue-runner.js +397 -0
- package/dist/mission-queue-runner.js.map +1 -0
- package/dist/multi-run-cli.d.ts +37 -0
- package/dist/multi-run-cli.js +110 -0
- package/dist/multi-run-cli.js.map +1 -0
- package/dist/multi-run.d.ts +339 -0
- package/dist/multi-run.js +619 -0
- package/dist/multi-run.js.map +1 -0
- package/dist/openrouter-call.d.ts +22 -0
- package/dist/openrouter-call.js +63 -0
- package/dist/openrouter-call.js.map +1 -0
- package/dist/profile-cli.d.ts +4 -0
- package/dist/profile-cli.js +57 -0
- package/dist/profile-cli.js.map +1 -0
- package/dist/program.d.ts +3 -75
- package/dist/program.js +119 -1921
- package/dist/program.js.map +1 -1
- package/dist/project-dir.d.ts +96 -0
- package/dist/project-dir.js +220 -0
- package/dist/project-dir.js.map +1 -0
- package/dist/record-api.d.ts +10 -6
- package/dist/record-api.js +39 -28
- package/dist/record-api.js.map +1 -1
- package/dist/record-cli.d.ts +4 -0
- package/dist/record-cli.js +64 -0
- package/dist/record-cli.js.map +1 -0
- package/dist/recording-cli.d.ts +4 -0
- package/dist/recording-cli.js +248 -0
- package/dist/recording-cli.js.map +1 -0
- package/dist/regression-api.d.ts +101 -0
- package/dist/regression-api.js +384 -5
- package/dist/regression-api.js.map +1 -1
- package/dist/regression-cli.d.ts +4 -0
- package/dist/regression-cli.js +232 -0
- package/dist/regression-cli.js.map +1 -0
- package/dist/report-api.d.ts +146 -0
- package/dist/report-api.js +430 -0
- package/dist/report-api.js.map +1 -0
- package/dist/report-cli.d.ts +12 -0
- package/dist/report-cli.js +147 -0
- package/dist/report-cli.js.map +1 -0
- package/dist/result-schema.d.ts +22 -0
- package/dist/result-schema.js +28 -0
- package/dist/result-schema.js.map +1 -0
- package/dist/run-index.d.ts +29 -0
- package/dist/run-index.js +70 -0
- package/dist/run-index.js.map +1 -0
- package/dist/run-screenshots.d.ts +123 -0
- package/dist/run-screenshots.js +229 -0
- package/dist/run-screenshots.js.map +1 -0
- package/dist/runtime-env.d.ts +8 -0
- package/dist/runtime-env.js +22 -0
- package/dist/runtime-env.js.map +1 -0
- package/dist/secret-args.d.ts +23 -0
- package/dist/secret-args.js +45 -0
- package/dist/secret-args.js.map +1 -0
- package/dist/serve-cli.d.ts +4 -0
- package/dist/serve-cli.js +95 -0
- package/dist/serve-cli.js.map +1 -0
- package/dist/server-log-verify.d.ts +34 -0
- package/dist/server-log-verify.js +115 -0
- package/dist/server-log-verify.js.map +1 -0
- package/dist/session-check.d.ts +14 -0
- package/dist/session-check.js +44 -0
- package/dist/session-check.js.map +1 -0
- package/dist/site-cli.d.ts +4 -0
- package/dist/site-cli.js +127 -0
- package/dist/site-cli.js.map +1 -0
- package/dist/site-gate-cli.d.ts +28 -0
- package/dist/site-gate-cli.js +58 -0
- package/dist/site-gate-cli.js.map +1 -0
- package/dist/source-api.js +18 -3
- package/dist/source-api.js.map +1 -1
- package/dist/source-cli.d.ts +4 -0
- package/dist/source-cli.js +284 -0
- package/dist/source-cli.js.map +1 -0
- package/dist/source-run-api.d.ts +27 -1
- package/dist/source-run-api.js +22 -11
- package/dist/source-run-api.js.map +1 -1
- package/dist/storage-state-snapshot.d.ts +50 -0
- package/dist/storage-state-snapshot.js +87 -0
- package/dist/storage-state-snapshot.js.map +1 -0
- package/dist/suite-explore-options.d.ts +289 -0
- package/dist/suite-explore-options.js +140 -0
- package/dist/suite-explore-options.js.map +1 -0
- package/dist/target-config.d.ts +109 -0
- package/dist/target-config.js +216 -0
- package/dist/target-config.js.map +1 -0
- package/dist/transcript-file.d.ts +12 -0
- package/dist/transcript-file.js +23 -0
- package/dist/transcript-file.js.map +1 -0
- package/dist/ui-api.d.ts +3 -0
- package/dist/ui-api.js +7 -1
- package/dist/ui-api.js.map +1 -1
- package/dist/usability-capture.d.ts +43 -0
- package/dist/usability-capture.js +326 -0
- package/dist/usability-capture.js.map +1 -0
- package/dist/usage-config.d.ts +36 -0
- package/dist/usage-config.js +114 -0
- package/dist/usage-config.js.map +1 -0
- package/dist/ux-api.d.ts +3 -75
- package/dist/ux-api.js +3 -220
- package/dist/ux-api.js.map +1 -1
- package/dist/ux-cli.d.ts +4 -0
- package/dist/ux-cli.js +102 -0
- package/dist/ux-cli.js.map +1 -0
- package/dist/ux-config.d.ts +29 -0
- package/dist/ux-config.js +103 -0
- package/dist/ux-config.js.map +1 -0
- package/dist/ux-evidence.d.ts +54 -0
- package/dist/ux-evidence.js +197 -0
- package/dist/ux-evidence.js.map +1 -0
- package/dist/ux-review.d.ts +112 -0
- package/dist/ux-review.js +151 -0
- package/dist/ux-review.js.map +1 -0
- package/dist/ux-usability.d.ts +238 -0
- package/dist/ux-usability.js +494 -0
- package/dist/ux-usability.js.map +1 -0
- package/dist/verify-fix-api.d.ts +173 -0
- package/dist/verify-fix-api.js +454 -0
- package/dist/verify-fix-api.js.map +1 -0
- package/dist/verify-fix-cli.d.ts +4 -0
- package/dist/verify-fix-cli.js +110 -0
- package/dist/verify-fix-cli.js.map +1 -0
- package/package.json +19 -14
- package/skills/jevitate-ci-check/SKILL.md +77 -0
- package/skills/jevitate-demo/SKILL.md +61 -0
- package/skills/jevitate-explore/SKILL.md +88 -87
- package/skills/jevitate-getting-started/SKILL.md +88 -0
- package/skills/jevitate-load-test/SKILL.md +11 -2
- package/skills/jevitate-mission-scope/SKILL.md +19 -11
- package/skills/jevitate-record/SKILL.md +23 -5
- package/skills/jevitate-run-journey/SKILL.md +61 -17
- package/skills/jevitate-sources/SKILL.md +57 -14
- package/skills/jevitate-ux-review/SKILL.md +106 -16
- package/skills/jevitate-verify-fix/SKILL.md +76 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
export const DEFAULT_JUDGMENT_BUDGET = 40;
|
|
2
|
+
function emptyBehavior() {
|
|
3
|
+
return { noProgress: false, backtracks: 0, formReentry: 0, dwellMs: 0, errors: 0 };
|
|
4
|
+
}
|
|
5
|
+
/** explore's live `Control` → ux `Control` (same shape by design; drop `stability`). */
|
|
6
|
+
function toUxControl(c) {
|
|
7
|
+
return {
|
|
8
|
+
index: c.index,
|
|
9
|
+
role: c.role,
|
|
10
|
+
name: c.name,
|
|
11
|
+
tag: c.tag,
|
|
12
|
+
inputType: c.inputType,
|
|
13
|
+
enabled: c.enabled,
|
|
14
|
+
summary: c.summary,
|
|
15
|
+
descriptor: c.descriptor,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** a11y facts computable from a live snapshot's controls (honest subset). */
|
|
19
|
+
function a11yFactsFromControls(controls) {
|
|
20
|
+
return {
|
|
21
|
+
controls: controls.map((c) => ({
|
|
22
|
+
controlRef: `control:${c.index}`,
|
|
23
|
+
accessibleName: c.name.trim().length > 0 ? c.name : null,
|
|
24
|
+
focusOrder: c.index,
|
|
25
|
+
targetSize: null,
|
|
26
|
+
contrastRatio: null,
|
|
27
|
+
})),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** A live Snapshot (+ extracted page text) → one screen's UxEvidence. */
|
|
31
|
+
export function snapshotToEvidence(snap, visibleText, appContext, job, history) {
|
|
32
|
+
const controls = snap.controls.map(toUxControl);
|
|
33
|
+
return {
|
|
34
|
+
screenId: snap.signature,
|
|
35
|
+
url: snap.url,
|
|
36
|
+
controls,
|
|
37
|
+
visibleText,
|
|
38
|
+
appContext,
|
|
39
|
+
...(job !== undefined ? { job } : {}),
|
|
40
|
+
history,
|
|
41
|
+
behavior: emptyBehavior(),
|
|
42
|
+
a11yFacts: a11yFactsFromControls(controls),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function descriptorSummary(d) {
|
|
46
|
+
const parts = [d.role, d.name ?? d.testId ?? d.text].filter((s) => !!s);
|
|
47
|
+
return parts.join(" ") || "control";
|
|
48
|
+
}
|
|
49
|
+
function stepTarget(step) {
|
|
50
|
+
if ("target" in step && step.target)
|
|
51
|
+
return step.target;
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Values the run itself typed or selected — a Recording's own `fill`/`select` steps whose value
|
|
56
|
+
* was NOT redacted (a secret field's value is always `{redacted:true}` and never surfaces here).
|
|
57
|
+
* #85 item 1: feeds the vocabulary/jargon tier (nielsen-2) so a quote/label that is really the
|
|
58
|
+
* user's own content (e.g. a piece title echoed back onto a card) is not mistaken for app copy.
|
|
59
|
+
*/
|
|
60
|
+
export function extractTypedValues(recording) {
|
|
61
|
+
const values = [];
|
|
62
|
+
for (const page of recording.pages) {
|
|
63
|
+
for (const rs of page.steps) {
|
|
64
|
+
const step = rs.step;
|
|
65
|
+
if ((step.kind === "fill" || step.kind === "select") && !("var" in step.value) && !step.value.redacted) {
|
|
66
|
+
values.push(step.value.value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return [...new Set(values)];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* #134: the run-signal capture a transcript ALONE supports (no visible text, no requests) — enough
|
|
74
|
+
* for the journey friction (retries, dead ends, waits, backtracks, abandoned fields) and repeated
|
|
75
|
+
* replies, NOT for the oracles that need requests or page text (they would misfire on the blanks).
|
|
76
|
+
*/
|
|
77
|
+
export function captureFromTranscript(transcript) {
|
|
78
|
+
const steps = transcript.map((t, i) => ({
|
|
79
|
+
step: t.step ?? i + 1,
|
|
80
|
+
op: t.op ?? null,
|
|
81
|
+
target: t.target ?? null,
|
|
82
|
+
actOk: t.actOk,
|
|
83
|
+
url: t.url,
|
|
84
|
+
...(t.descriptor === undefined ? {} : { descriptor: t.descriptor }),
|
|
85
|
+
...(t.reason === undefined ? {} : { reason: t.reason }),
|
|
86
|
+
...(t.value === undefined ? {} : { value: t.value }),
|
|
87
|
+
...(t.message === undefined ? {} : { message: t.message }),
|
|
88
|
+
...(t.reply?.text === undefined || t.reply.received === false ? {} : { reply: t.reply.text }),
|
|
89
|
+
}));
|
|
90
|
+
const screens = transcript.map((t, i) => ({
|
|
91
|
+
index: i,
|
|
92
|
+
step: t.step ?? i + 1,
|
|
93
|
+
at: 0,
|
|
94
|
+
url: t.url,
|
|
95
|
+
signature: t.signature ?? `step:${t.step ?? i + 1}`,
|
|
96
|
+
visibleText: "",
|
|
97
|
+
busy: false,
|
|
98
|
+
...(t.screenshot === undefined ? {} : { screenshot: t.screenshot }),
|
|
99
|
+
}));
|
|
100
|
+
return { steps, requests: [], screens, endedAt: 0 };
|
|
101
|
+
}
|
|
102
|
+
const ACTIONABLE_OPS = new Set(["click", "type", "select"]);
|
|
103
|
+
/**
|
|
104
|
+
* Blocked/disabled-target controls derived from a mission transcript (#85 item 2), grouped by the
|
|
105
|
+
* page url they were observed on. A failed action is never recorded as a Recording step (see #81:
|
|
106
|
+
* `RunRecorder` records only successful actions), so this is the only source that gives offline
|
|
107
|
+
* `jevitate ux` the same evidence a LIVE usability run sees for free via `Control.enabled` on its
|
|
108
|
+
* snapshot — e.g. a "Pay" button that stayed disabled.
|
|
109
|
+
*/
|
|
110
|
+
function blockedControlsByUrl(transcript, startIndex) {
|
|
111
|
+
const byUrl = new Map();
|
|
112
|
+
const seen = new Set();
|
|
113
|
+
let idx = startIndex;
|
|
114
|
+
for (const t of transcript) {
|
|
115
|
+
if (t.actOk || t.descriptor === undefined || !t.op || !ACTIONABLE_OPS.has(t.op))
|
|
116
|
+
continue;
|
|
117
|
+
const key = `${t.url}|${JSON.stringify(t.descriptor)}`;
|
|
118
|
+
if (seen.has(key))
|
|
119
|
+
continue;
|
|
120
|
+
seen.add(key);
|
|
121
|
+
const d = t.descriptor;
|
|
122
|
+
const list = byUrl.get(t.url) ?? [];
|
|
123
|
+
list.push({
|
|
124
|
+
index: idx++,
|
|
125
|
+
role: d.role ?? "",
|
|
126
|
+
name: d.name ?? d.testId ?? d.text ?? "",
|
|
127
|
+
tag: "",
|
|
128
|
+
inputType: null,
|
|
129
|
+
enabled: false,
|
|
130
|
+
summary: `${descriptorSummary(d)} (blocked: ${t.reason ?? "action did not succeed"})`,
|
|
131
|
+
descriptor: d,
|
|
132
|
+
});
|
|
133
|
+
byUrl.set(t.url, list);
|
|
134
|
+
}
|
|
135
|
+
return byUrl;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A saved Recording → per-page UxEvidence. A Recording is deterministic and
|
|
139
|
+
* thin: it carries the CONTROLS the user touched (via each step's descriptor)
|
|
140
|
+
* and the page url, but NOT the full visible text or a11y geometry. So offline
|
|
141
|
+
* analysis is honestly partial — items needing `visibleText`/`a11yFacts` Skip,
|
|
142
|
+
* and coverage reports it. (The live mode carries the rich per-screen snapshot.)
|
|
143
|
+
*
|
|
144
|
+
* `missionTranscript` (#85 item 2, optional) adds blocked/disabled-target controls the Recording
|
|
145
|
+
* itself cannot carry, on whichever screen(s) share the blocked action's url — the same evidence a
|
|
146
|
+
* live usability run gets from its snapshot. `typedValues` (every screen's own #85 item 1 input)
|
|
147
|
+
* is always derived from the Recording, with or without a transcript.
|
|
148
|
+
*/
|
|
149
|
+
export function recordingToEvidence(recording, appContext, job, missionTranscript) {
|
|
150
|
+
const screens = [];
|
|
151
|
+
const history = [];
|
|
152
|
+
const typedValues = extractTypedValues(recording);
|
|
153
|
+
const blockedByUrl = blockedControlsByUrl(missionTranscript ?? [], recording.pages.reduce((n, p) => n + p.steps.length, 0) + 1000);
|
|
154
|
+
for (let i = 0; i < recording.pages.length; i++) {
|
|
155
|
+
const page = recording.pages[i];
|
|
156
|
+
const controls = [];
|
|
157
|
+
let idx = 0;
|
|
158
|
+
const seen = new Set();
|
|
159
|
+
for (const rs of page.steps) {
|
|
160
|
+
const d = stepTarget(rs.step);
|
|
161
|
+
if (!d)
|
|
162
|
+
continue;
|
|
163
|
+
const key = JSON.stringify(d);
|
|
164
|
+
if (seen.has(key))
|
|
165
|
+
continue;
|
|
166
|
+
seen.add(key);
|
|
167
|
+
controls.push({
|
|
168
|
+
index: idx++,
|
|
169
|
+
role: d.role ?? "",
|
|
170
|
+
name: d.name ?? d.testId ?? d.text ?? "",
|
|
171
|
+
tag: "",
|
|
172
|
+
inputType: null,
|
|
173
|
+
enabled: true,
|
|
174
|
+
summary: descriptorSummary(d),
|
|
175
|
+
descriptor: d,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
for (const blocked of blockedByUrl.get(page.url) ?? [])
|
|
179
|
+
controls.push(blocked);
|
|
180
|
+
const screenId = `${page.url}#${i}`;
|
|
181
|
+
screens.push({
|
|
182
|
+
screenId,
|
|
183
|
+
url: page.url,
|
|
184
|
+
controls,
|
|
185
|
+
visibleText: "",
|
|
186
|
+
appContext,
|
|
187
|
+
...(job !== undefined ? { job } : {}),
|
|
188
|
+
history: [...history],
|
|
189
|
+
behavior: emptyBehavior(),
|
|
190
|
+
a11yFacts: { controls: [] },
|
|
191
|
+
...(typedValues.length > 0 ? { typedValues } : {}),
|
|
192
|
+
});
|
|
193
|
+
history.push({ screenId, url: page.url });
|
|
194
|
+
}
|
|
195
|
+
return screens;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=ux-evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ux-evidence.js","sourceRoot":"","sources":["../src/ux-evidence.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAE1C,SAAS,aAAa;IACpB,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAW,CAAC;AAC9F,CAAC;AAED,wFAAwF;AACxF,SAAS,WAAW,CAAC,CAAiB;IACpC,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,UAAU,EAAE,CAAC,CAAC,UAAU;KACzB,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,SAAS,qBAAqB,CAAC,QAA8B;IAC3D,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,UAAU,EAAE,WAAW,CAAC,CAAC,KAAK,EAAE;YAChC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;YACxD,UAAU,EAAE,CAAC,CAAC,KAAK;YACnB,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,kBAAkB,CAChC,IAAc,EACd,WAAmB,EACnB,UAAsB,EACtB,GAAuB,EACvB,OAA6B;IAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAChD,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,SAAS;QACxB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,QAAQ;QACR,WAAW;QACX,UAAU;QACV,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO;QACP,QAAQ,EAAE,aAAa,EAAE;QACzB,SAAS,EAAE,qBAAqB,CAAC,QAAQ,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAmB;IAC5C,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,IAAyD;IAC3E,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC;IACxD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAoB;IACrD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QACnC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACvG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9B,CAAC;AAsBD;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAiD;IACrF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACtC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC;QACrB,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,IAAI;QAChB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI;QACxB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,GAAG,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;QACnE,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QACvD,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACpD,GAAG,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;QAC1D,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;KAC9F,CAAC,CAAC,CAAC;IACJ,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxC,KAAK,EAAE,CAAC;QACR,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC;QACrB,EAAE,EAAE,CAAC;QACL,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE;QACnD,WAAW,EAAE,EAAE;QACf,IAAI,EAAE,KAAK;QACX,GAAG,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;KACpE,CAAC,CAAC,CAAC;IACJ,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE5D;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,UAAiD,EAAE,UAAkB;IACjG,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,GAAG,GAAG,UAAU,CAAC;IACrB,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QAC1F,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;QACvD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC;YACR,KAAK,EAAE,GAAG,EAAE;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;YAClB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE;YACxC,GAAG,EAAE,EAAE;YACP,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,GAAG,iBAAiB,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,IAAI,wBAAwB,GAAG;YACrF,UAAU,EAAE,CAAC;SACd,CAAC,CAAC;QACH,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAoB,EACpB,UAAsB,EACtB,GAAY,EACZ,iBAAyD;IAEzD,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,MAAM,WAAW,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,oBAAoB,CAAC,iBAAiB,IAAI,EAAE,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACnI,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAgB,EAAE,CAAC;QACjC,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,GAAG,EAAE;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;gBAClB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE;gBACxC,GAAG,EAAE,EAAE;gBACP,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;gBAC7B,UAAU,EAAE,CAAC;aACd,CAAC,CAAC;QACL,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/E,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ;YACR,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ;YACR,WAAW,EAAE,EAAE;YACf,UAAU;YACV,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;YACrB,QAAQ,EAAE,aAAa,EAAE;YACzB,SAAS,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC3B,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { JudgmentPort, GenerationPort, UsageTracker, UsageCounts } from "@jevitate/ai-core";
|
|
2
|
+
import type { Recording } from "@jevitate/recording";
|
|
3
|
+
import { type AppContext, type JourneyOutcome, type SignalOptions, type UxEvidenceFile, type UxReport } from "@jevitate/ux";
|
|
4
|
+
import { type MissionTranscriptEntryLike } from "./ux-evidence.js";
|
|
5
|
+
export interface RunUxReviewOptions {
|
|
6
|
+
readonly recording: Recording;
|
|
7
|
+
readonly appContext: AppContext;
|
|
8
|
+
readonly judge: JudgmentPort;
|
|
9
|
+
/** Structured-output specifics (observation / implicated controls / fix) for flagged items. */
|
|
10
|
+
readonly gen: GenerationPort;
|
|
11
|
+
/**
|
|
12
|
+
* Usage accounting (#100): when supplied, its snapshot (judgments/generations/tokens/`usd`) lands
|
|
13
|
+
* in the result as `usage`. The CLI builds one per invocation and hands it to `judge`/`gen`.
|
|
14
|
+
*/
|
|
15
|
+
readonly usage?: UsageTracker;
|
|
16
|
+
/**
|
|
17
|
+
* Report cutoff; findings below it are suppressed (counted in `report.suppressed`). Precedence:
|
|
18
|
+
* this (CLI `--min-confidence`) > `JEVITATE_UX_MIN_CONFIDENCE` > config `ux.minConfidence`
|
|
19
|
+
* (`~/.jevitate/config.json`) > `DEFAULT_MIN_CONFIDENCE`.
|
|
20
|
+
*/
|
|
21
|
+
readonly minConfidence?: number | string;
|
|
22
|
+
/**
|
|
23
|
+
* Quality grades to show, e.g. "actionable,relevant-minor". Precedence: this (CLI `--show`) >
|
|
24
|
+
* `JEVITATE_UX_SHOW` > config `ux.show` > every grade (#133: the uncalibrated grader labels, it does not filter).
|
|
25
|
+
*/
|
|
26
|
+
readonly show?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Cap on findings per route (issue #198 interim, 0.2.0). Precedence: this (CLI
|
|
29
|
+
* `--max-findings-per-page`) > `JEVITATE_UX_MAX_FINDINGS_PER_PAGE` > config
|
|
30
|
+
* `ux.maxFindingsPerPage` > `DEFAULT_MAX_FINDINGS_PER_ROUTE` (5).
|
|
31
|
+
*/
|
|
32
|
+
readonly maxFindingsPerRoute?: number | string;
|
|
33
|
+
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
34
|
+
/** Path of the config file holding `ux.minConfidence`. Default `~/.jevitate/config.json`. */
|
|
35
|
+
readonly configPath?: string;
|
|
36
|
+
readonly secrets?: readonly string[];
|
|
37
|
+
/** Local file the `upload` op attaches (CLI `--fixture`); validated before any browser opens. */
|
|
38
|
+
readonly fixture?: string;
|
|
39
|
+
readonly judgmentBudget?: number;
|
|
40
|
+
/** Where to write the report. Default `.jevitate/logs/<date>` (project, else `~/.jevitate`). */
|
|
41
|
+
readonly outDir?: string;
|
|
42
|
+
readonly nowIso?: () => string;
|
|
43
|
+
/**
|
|
44
|
+
* The source run's mission transcript (#85 item 2) — from `--result`'s `<recording>.result.json`
|
|
45
|
+
* (`result.transcript`), or the sibling `<recording>.transcript.json` directly. Gives offline
|
|
46
|
+
* analysis the same blocked/disabled-target evidence a live usability run sees. Absent, the
|
|
47
|
+
* report says so (`report.evidenceCaveats`) rather than silently seeing less.
|
|
48
|
+
*/
|
|
49
|
+
readonly missionTranscript?: readonly MissionTranscriptEntryLike[];
|
|
50
|
+
/** Why `missionTranscript` is absent (e.g. no `--result` given, or the file could not be read) — becomes a report caveat. */
|
|
51
|
+
readonly missionTranscriptUnavailable?: string;
|
|
52
|
+
/** The source run's end state (a mission result's `outcome`), for the goal-not-reached friction (#132). */
|
|
53
|
+
readonly missionOutcome?: JourneyOutcome;
|
|
54
|
+
/**
|
|
55
|
+
* #134: the live usability run's evidence sidecar (`<stamp>.evidence.json`): every screen as the
|
|
56
|
+
* live analyzer saw it (redacted) and the run-signal capture. With it, offline review reproduces
|
|
57
|
+
* the live run's rubric AND signal findings; without it, the report says what it could not see.
|
|
58
|
+
*/
|
|
59
|
+
readonly evidenceFile?: UxEvidenceFile;
|
|
60
|
+
/** Why no evidence sidecar was used (not found next to the Recording, or unreadable) — a report caveat. */
|
|
61
|
+
readonly evidenceUnavailable?: string;
|
|
62
|
+
/** Tuning of the run-signal oracles (#96/#131). */
|
|
63
|
+
readonly signals?: SignalOptions;
|
|
64
|
+
}
|
|
65
|
+
export interface RunUxReviewResult {
|
|
66
|
+
readonly report: UxReport;
|
|
67
|
+
readonly reportPath: string;
|
|
68
|
+
/** Judgment/generation call counts and tokens for this run (#100); present only when `opts.usage` was supplied. */
|
|
69
|
+
readonly usage?: UsageCounts;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Offline UX review. FAIL-FAST: an analyzer `failed` outcome throws
|
|
73
|
+
* `UxAnalysisFailedError` (the CLI maps it to a non-zero fail envelope) — never
|
|
74
|
+
* a fabricated "clean" report.
|
|
75
|
+
*/
|
|
76
|
+
export declare function runUxReview(opts: RunUxReviewOptions): Promise<RunUxReviewResult>;
|
|
77
|
+
/** #134: the artifacts a run writes next to its Recording (`<stem>.recording.json`). */
|
|
78
|
+
export interface RecordingSidecars {
|
|
79
|
+
/** `<stem>.evidence.json` — the live usability run's evidence sidecar. */
|
|
80
|
+
readonly evidencePath?: string;
|
|
81
|
+
/** `<stem>.transcript.json` — the decision transcript (each step's screenshot). */
|
|
82
|
+
readonly transcriptPath?: string;
|
|
83
|
+
/** `<stem>.result.json` — a mission result (explore/adversarial), carrying transcript + outcome. */
|
|
84
|
+
readonly resultPath?: string;
|
|
85
|
+
/** `<stem>.screens/` — the per-step screenshots. */
|
|
86
|
+
readonly screenshotDir?: string;
|
|
87
|
+
}
|
|
88
|
+
/** Finds the sidecars that exist next to `recordingPath` (only `<stem>.recording.json` has a stem). */
|
|
89
|
+
export declare function discoverRecordingSidecars(recordingPath: string): RecordingSidecars;
|
|
90
|
+
/** What the discovered (or given) sidecars supply to `runUxReview`, and why anything is missing. */
|
|
91
|
+
export interface LoadedSidecars {
|
|
92
|
+
readonly evidenceFile?: UxEvidenceFile;
|
|
93
|
+
readonly evidenceUnavailable?: string;
|
|
94
|
+
readonly missionTranscript?: MissionTranscriptEntryLike[];
|
|
95
|
+
readonly missionTranscriptUnavailable?: string;
|
|
96
|
+
readonly missionOutcome?: JourneyOutcome;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Reads the evidence sidecar and the transcript/result (explicit paths win over discovered ones).
|
|
100
|
+
* Never throws: an unreadable file becomes the matching `…Unavailable` caveat.
|
|
101
|
+
*/
|
|
102
|
+
export declare function loadRecordingSidecars(paths: {
|
|
103
|
+
readonly evidencePath?: string;
|
|
104
|
+
readonly resultPath?: string;
|
|
105
|
+
readonly transcriptPath?: string;
|
|
106
|
+
}): Promise<LoadedSidecars>;
|
|
107
|
+
export declare class UxAnalysisFailedError extends Error {
|
|
108
|
+
readonly screenId?: string | undefined;
|
|
109
|
+
readonly rubricItemId?: string | undefined;
|
|
110
|
+
readonly code: "E_UX_ANALYSIS";
|
|
111
|
+
constructor(reason: string, screenId?: string | undefined, rubricItemId?: string | undefined);
|
|
112
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// ux-review.ts — offline UX review of a saved Recording (`jevitate ux`) (#231).
|
|
2
|
+
import { logsDirFor } from "./project-dir.js";
|
|
3
|
+
import { existsSync, statSync } from "node:fs";
|
|
4
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { UxAnalyzer, a11yChecks, buildReport, calibrationCaveat, detectFriction, detectRepeatedReplies, detectSignals, evidenceFromFile, groundFindings, loadV1Rubric, parseUxEvidenceFile, resolveMinConfidence, resolveMaxFindingsPerRoute, resolveQualityPolicy, withSignalFindings } from "@jevitate/ux";
|
|
7
|
+
import { loadUxMaxFindingsPerPage, loadUxMinConfidence, loadUxMinConfidenceByAppClass, loadUxShow } from "./ux-config.js";
|
|
8
|
+
import { writeUsageSidecar } from "./mission-journal.js";
|
|
9
|
+
import { DEFAULT_JUDGMENT_BUDGET, captureFromTranscript, recordingToEvidence } from "./ux-evidence.js";
|
|
10
|
+
const NO_EVIDENCE_CAVEAT = "no usability evidence sidecar (<stamp>.evidence.json, written next to the Recording by live usability runs, #134): this pass sees only the Recording's touched controls and urls — rubric items needing visible text or a11y facts are Skipped, and the run signals that need the live capture (hung request, stuck job, duplicate write/create, failed submit, inert control, internal id, url mismatch) could not be checked; with a transcript, journey friction and repeated replies still are.";
|
|
11
|
+
const NO_TRANSCRIPT_CAVEAT = "blocked/disabled-target evidence not available: this offline pass has no mission transcript, so a dead end like a button that never enables cannot be seen (pass --result <mission-result.json>, as written by `jevitate explore`, to include it — the same evidence a live usability run sees).";
|
|
12
|
+
/**
|
|
13
|
+
* Offline UX review. FAIL-FAST: an analyzer `failed` outcome throws
|
|
14
|
+
* `UxAnalysisFailedError` (the CLI maps it to a non-zero fail envelope) — never
|
|
15
|
+
* a fabricated "clean" report.
|
|
16
|
+
*/
|
|
17
|
+
export async function runUxReview(opts) {
|
|
18
|
+
// #163: this review's own share of a (possibly shared) tracker.
|
|
19
|
+
const runUsage = opts.usage?.scope();
|
|
20
|
+
const minConfidence = resolveMinConfidence(opts.minConfidence, opts.env ?? process.env, loadUxMinConfidence(opts.configPath), loadUxMinConfidenceByAppClass(opts.configPath, opts.appContext.appClass));
|
|
21
|
+
const quality = resolveQualityPolicy(opts.show, opts.env ?? process.env, loadUxShow(opts.configPath), opts.appContext.appClass);
|
|
22
|
+
const maxFindingsPerRoute = resolveMaxFindingsPerRoute(opts.maxFindingsPerRoute, opts.env ?? process.env, loadUxMaxFindingsPerPage(opts.configPath));
|
|
23
|
+
const analyzer = new UxAnalyzer({ judge: opts.judge, gen: opts.gen, a11yChecker: a11yChecks });
|
|
24
|
+
// #134: a live usability run's evidence sidecar gives offline review the SAME screens and run
|
|
25
|
+
// signals the live analysis had; otherwise the Recording (+ transcript) is all there is.
|
|
26
|
+
let screens;
|
|
27
|
+
let appContext = opts.appContext;
|
|
28
|
+
let signalFindings = [];
|
|
29
|
+
let friction = [];
|
|
30
|
+
const evidenceCaveats = [];
|
|
31
|
+
if (opts.evidenceFile !== undefined) {
|
|
32
|
+
({ screens, appContext } = evidenceFromFile(opts.evidenceFile, opts.appContext));
|
|
33
|
+
signalFindings = detectSignals(opts.evidenceFile.signals, opts.signals);
|
|
34
|
+
friction = detectFriction(opts.evidenceFile.signals, opts.evidenceFile.outcome ?? opts.missionOutcome);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
screens = recordingToEvidence(opts.recording, opts.appContext, opts.appContext.job, opts.missionTranscript);
|
|
38
|
+
if (opts.missionTranscript !== undefined) {
|
|
39
|
+
const partial = captureFromTranscript(opts.missionTranscript);
|
|
40
|
+
signalFindings = detectRepeatedReplies(partial, opts.signals);
|
|
41
|
+
friction = detectFriction(partial, opts.missionOutcome);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
evidenceCaveats.push(opts.missionTranscriptUnavailable ?? NO_TRANSCRIPT_CAVEAT);
|
|
45
|
+
}
|
|
46
|
+
evidenceCaveats.push(opts.evidenceUnavailable === undefined ? NO_EVIDENCE_CAVEAT : `${opts.evidenceUnavailable} — ${NO_EVIDENCE_CAVEAT}`);
|
|
47
|
+
}
|
|
48
|
+
const outcome = await analyzer.analyze({
|
|
49
|
+
screens,
|
|
50
|
+
rubric: loadV1Rubric(),
|
|
51
|
+
appContext,
|
|
52
|
+
secrets: opts.secrets,
|
|
53
|
+
judgmentBudget: opts.judgmentBudget ?? DEFAULT_JUDGMENT_BUDGET,
|
|
54
|
+
});
|
|
55
|
+
if (outcome.kind === "failed") {
|
|
56
|
+
throw new UxAnalysisFailedError(outcome.reason, outcome.screenId, outcome.rubricItemId);
|
|
57
|
+
}
|
|
58
|
+
const calibrationCaveats = [calibrationCaveat(opts.appContext.appClass)];
|
|
59
|
+
const report = buildReport(groundFindings(withSignalFindings(outcome, signalFindings), friction), {
|
|
60
|
+
minConfidence,
|
|
61
|
+
quality,
|
|
62
|
+
maxFindingsPerRoute,
|
|
63
|
+
evidenceCaveats,
|
|
64
|
+
calibrationCaveats,
|
|
65
|
+
});
|
|
66
|
+
const outDir = opts.outDir ?? logsDirFor();
|
|
67
|
+
await mkdir(outDir, { recursive: true });
|
|
68
|
+
const iso = (opts.nowIso ?? (() => new Date().toISOString()))();
|
|
69
|
+
const reportPath = join(outDir, `ux-${iso.replace(/[:.]/g, "-")}.json`);
|
|
70
|
+
await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
|
|
71
|
+
if (runUsage !== undefined)
|
|
72
|
+
writeUsageSidecar(reportPath, runUsage);
|
|
73
|
+
return { report, reportPath, ...(runUsage === undefined ? {} : { usage: runUsage.snapshot() }) };
|
|
74
|
+
}
|
|
75
|
+
/** Finds the sidecars that exist next to `recordingPath` (only `<stem>.recording.json` has a stem). */
|
|
76
|
+
export function discoverRecordingSidecars(recordingPath) {
|
|
77
|
+
if (!recordingPath.endsWith(".recording.json"))
|
|
78
|
+
return {};
|
|
79
|
+
const stem = recordingPath.slice(0, -".recording.json".length);
|
|
80
|
+
const file = (p) => (existsSync(p) && statSync(p).isFile() ? p : undefined);
|
|
81
|
+
const dir = (p) => (existsSync(p) && statSync(p).isDirectory() ? p : undefined);
|
|
82
|
+
const evidencePath = file(`${stem}.evidence.json`);
|
|
83
|
+
const transcriptPath = file(`${stem}.transcript.json`);
|
|
84
|
+
const resultPath = file(`${stem}.result.json`);
|
|
85
|
+
const screenshotDir = dir(`${stem}.screens`);
|
|
86
|
+
return {
|
|
87
|
+
...(evidencePath === undefined ? {} : { evidencePath }),
|
|
88
|
+
...(transcriptPath === undefined ? {} : { transcriptPath }),
|
|
89
|
+
...(resultPath === undefined ? {} : { resultPath }),
|
|
90
|
+
...(screenshotDir === undefined ? {} : { screenshotDir }),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function asOutcome(v) {
|
|
94
|
+
if (v === null || typeof v !== "object")
|
|
95
|
+
return undefined;
|
|
96
|
+
const o = v;
|
|
97
|
+
if (o.status === "completed")
|
|
98
|
+
return { status: "completed" };
|
|
99
|
+
if (o.status === "incomplete")
|
|
100
|
+
return { status: "incomplete", reason: typeof o.reason === "string" ? o.reason : "not completed" };
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Reads the evidence sidecar and the transcript/result (explicit paths win over discovered ones).
|
|
105
|
+
* Never throws: an unreadable file becomes the matching `…Unavailable` caveat.
|
|
106
|
+
*/
|
|
107
|
+
export async function loadRecordingSidecars(paths) {
|
|
108
|
+
const out = {};
|
|
109
|
+
if (paths.evidencePath !== undefined) {
|
|
110
|
+
try {
|
|
111
|
+
out.evidenceFile = parseUxEvidenceFile(JSON.parse(await readFile(paths.evidencePath, "utf8")));
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
out.evidenceUnavailable = `could not read the evidence sidecar ${paths.evidencePath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
out.evidenceUnavailable = "no evidence sidecar next to the Recording";
|
|
119
|
+
}
|
|
120
|
+
const source = paths.resultPath ?? paths.transcriptPath;
|
|
121
|
+
if (source !== undefined) {
|
|
122
|
+
try {
|
|
123
|
+
const raw = JSON.parse(await readFile(source, "utf8"));
|
|
124
|
+
const obj = (raw ?? {});
|
|
125
|
+
const transcript = Array.isArray(raw) ? raw : (obj.result?.transcript ?? obj.transcript);
|
|
126
|
+
if (Array.isArray(transcript))
|
|
127
|
+
out.missionTranscript = transcript;
|
|
128
|
+
else
|
|
129
|
+
out.missionTranscriptUnavailable = `${source} has no transcript`;
|
|
130
|
+
const outcome = Array.isArray(raw) ? undefined : asOutcome(obj.result?.outcome ?? obj.outcome);
|
|
131
|
+
if (outcome !== undefined)
|
|
132
|
+
out.missionOutcome = outcome;
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
out.missionTranscriptUnavailable = `could not read ${source}: ${err instanceof Error ? err.message : String(err)}`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
export class UxAnalysisFailedError extends Error {
|
|
141
|
+
screenId;
|
|
142
|
+
rubricItemId;
|
|
143
|
+
code = "E_UX_ANALYSIS";
|
|
144
|
+
constructor(reason, screenId, rubricItemId) {
|
|
145
|
+
super(`UX analysis failed: ${reason}${screenId ? ` (screen ${screenId})` : ""}`);
|
|
146
|
+
this.screenId = screenId;
|
|
147
|
+
this.rubricItemId = rubricItemId;
|
|
148
|
+
this.name = "UxAnalysisFailedError";
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=ux-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ux-review.js","sourceRoot":"","sources":["../src/ux-review.ts"],"names":[],"mappings":"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"}
|