kaloko 0.4.8 → 0.4.10

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.
Files changed (51) hide show
  1. package/README.md +92 -5
  2. package/package.json +1 -1
  3. package/schemas/config.v1.json +33 -0
  4. package/schemas/scenario.v1.json +39 -0
  5. package/schemas/spec.v1.json +60 -0
  6. package/skills/kaloko/SKILL.md +24 -3
  7. package/skills/kaloko/reference/acceptance.md +50 -2
  8. package/skills/kaloko/reference/ci.md +70 -0
  9. package/skills/kaloko/reference/collaboration.md +9 -1
  10. package/skills/kaloko/reference/design.md +35 -2
  11. package/skills/kaloko/reference/environments.md +5 -0
  12. package/skills/kaloko/reference/evaluation.md +46 -3
  13. package/skills/kaloko/reference/execution.md +74 -0
  14. package/skills/kaloko/reference/import.md +66 -0
  15. package/skills/kaloko/reference/mcp.md +4 -1
  16. package/src/cli.mjs +428 -99
  17. package/src/lib/affected-core.mjs +242 -0
  18. package/src/lib/affected.mjs +233 -0
  19. package/src/lib/build.mjs +30 -5
  20. package/src/lib/capture.mjs +43 -1
  21. package/src/lib/ci.mjs +207 -0
  22. package/src/lib/config.mjs +2 -0
  23. package/src/lib/design-cli.mjs +7 -3
  24. package/src/lib/devspec.mjs +821 -0
  25. package/src/lib/doctor.mjs +7 -0
  26. package/src/lib/drift.mjs +16 -8
  27. package/src/lib/evaluate.mjs +98 -14
  28. package/src/lib/git.mjs +6 -2
  29. package/src/lib/heal.mjs +207 -0
  30. package/src/lib/import.mjs +374 -0
  31. package/src/lib/init-detect.mjs +219 -0
  32. package/src/lib/keyboard.mjs +261 -0
  33. package/src/lib/manifest-core.mjs +16 -5
  34. package/src/lib/onboarding.mjs +15 -8
  35. package/src/lib/pack-help.mjs +7 -0
  36. package/src/lib/packs.mjs +9 -2
  37. package/src/lib/png.mjs +61 -0
  38. package/src/lib/pr.mjs +24 -2
  39. package/src/lib/probe.mjs +57 -0
  40. package/src/lib/recheck.mjs +3 -1
  41. package/src/lib/scenario.mjs +2 -1
  42. package/src/lib/service.mjs +7 -1
  43. package/src/lib/spec-cli.mjs +90 -0
  44. package/src/lib/stability-core.mjs +114 -0
  45. package/src/lib/stability.mjs +249 -0
  46. package/src/lib/unzip.mjs +31 -0
  47. package/src/lib/upload.mjs +114 -0
  48. package/src/lib/vision-core.mjs +132 -0
  49. package/src/lib/vision.mjs +127 -0
  50. package/templates/kaloko.config.yml +6 -0
  51. package/viewer/index.html +500 -44
@@ -10,9 +10,11 @@ answer, so running it again is cheap.
10
10
  - deterministic results computed in the live page at capture time (with
11
11
  evidence: selector snippet, measured value);
12
12
  - the semantic evaluator for semantic criteria. It is a replaceable provider;
13
- the default is JEV by TypeSafe (`TYPESAFE_API_KEY`), which returns only a
14
- probability per question (`score`, 0–1). Verdicts: `pass` ≥ 0.85,
15
- `fail` ≤ 0.15, otherwise `needs_review` (thresholds in config);
13
+ the default is JEV by TypeSafe (`TYPESAFE_API_KEY`), which reads the
14
+ reduced page state (no images) and returns only a probability per question
15
+ (`score`, 0–1). Verdicts: `pass` ≥ 0.85, `fail` ≤ 0.15, otherwise
16
+ `needs_review` (thresholds in config);
17
+ - a vision evaluator for a second look with the screenshot (below);
16
18
  - `manual` criteria stay `not_evaluated` until a reviewer decides.
17
19
 
18
20
  Where the evaluator runs: with `TYPESAFE_API_KEY` set locally, your own key; without it, the organization's
@@ -25,6 +27,47 @@ report with the reason `kaloko evaluate` gives.
25
27
  The default evaluator is text-only and most accurate in English. It is weak
26
28
  at numbers, which is why those are checked deterministically.
27
29
 
30
+ ## Vision and reasons
31
+
32
+ Every semantic verdict carries one sentence, `reason`, shown as "Why" next to
33
+ the score on the canvas, in `kaloko build`, in the walk summary and in
34
+ `get_run_summary`. With only the text evaluator the sentence says what it
35
+ read and how sure it was (JEV gives no explanation). The vision evaluator
36
+ gives a real one: it sees the screenshot, or a crop of the criterion's
37
+ `scope` (or `highlight`), and answers with a probability and what in the
38
+ image decided it. It is asked for:
39
+
40
+ - criteria with `vision: true` on the check (layout, imagery, "looks like the
41
+ brand", anything the text cannot show);
42
+ - text answers in the uncertain band (0.15–0.85 by default), which would
43
+ otherwise go to a person.
44
+
45
+ Its answer replaces the score (the text score stays as `text_score` in the
46
+ evaluation). Cost stays bounded: only those criteria, one request per
47
+ capture, images scaled to 1000 px wide and at most two tiles of a full page,
48
+ at most 40 uncached requests per evaluation, and answers cached by content
49
+ like the text ones. The provider is Anthropic's Messages API
50
+ (`ANTHROPIC_API_KEY`, model from `evaluators.vision.model`, default
51
+ `claude-opus-5-5`). Without the key it goes through the organization's
52
+ service, where one vision question counts as five of the monthly allowance;
53
+ when the text evaluator runs with your own `TYPESAFE_API_KEY`, the vision
54
+ evaluator also waits for your own key (`evaluators.vision.hosted: true`
55
+ lets it use the service anyway).
56
+ Configure or switch it off in `kaloko.config.yml`:
57
+
58
+ ```yaml
59
+ evaluators:
60
+ vision:
61
+ when: uncertain # flagged (only vision: true) | always | off
62
+ uncertain: [0.15, 0.85]
63
+ max_calls: 40
64
+ reason_language: en # cs for Czech reviewers
65
+ # vision: false # text evaluator only
66
+ ```
67
+
68
+ Report the reason with each `needs_review` or failing criterion; when the
69
+ evaluator saw the screenshot, say so.
70
+
28
71
  When a criterion comes back `needs_review`, read the reduced state the
29
72
  evaluator saw (`steps/<node>/<locale>/<viewport>.capture.json`, key `state`)
30
73
  and the screenshot. Either the page is genuinely unclear (report it), the
@@ -73,3 +73,77 @@ The environment policy and gate apply to every context the CLI creates (the
73
73
  shared browser, `walk` sessions, one-off captures): blocked paths and, when
74
74
  readonly, non-GET requests outside `allowed_post_paths` fail and are listed as
75
75
  blocked requests in the capture; the gate's credentials go to its origins only.
76
+
77
+ ## Noisy regions (`--stability`, `kaloko stability`)
78
+
79
+ When pixel diffs between runs keep flagging the same clock, ad or carousel:
80
+
81
+ ```bash
82
+ kaloko walk --stability 3 # 3 screenshots per capture, a moment apart; what moved is noted
83
+ kaloko stability # this run against the 3 previous local runs of the scenario
84
+ kaloko stability --apply # adds the suggested ignore: to each step (block-style YAML only)
85
+ ```
86
+
87
+ `kaloko stability` writes `stability.json` and `stability.yml` into the run
88
+ and prints the suggestions per step: a selector when an element of the stored
89
+ page covers the region, otherwise a rectangle for one viewport. Look at the
90
+ screenshots before applying; a region that changed because the page really
91
+ changed is not noise. `--same-commit` compares only runs of the same commit,
92
+ `--runs a,b` names them, `--last N` sets how many runs are compared. Capture
93
+ the steps again after applying: the capture records the ignored regions.
94
+
95
+ ## Only what changed
96
+
97
+ After a fix, walk the steps the change reaches instead of the whole flow:
98
+
99
+ ```bash
100
+ kaloko affected # which steps, and why (against origin/main; --base <ref>)
101
+ kaloko walk --affected [--carry] # walk them; --carry copies the other steps from the previous local run
102
+ ```
103
+
104
+ A changed file reaches a step when it is a route file whose route matches the
105
+ step's path or a URL captured for it earlier (Next.js `app/` and `pages/`,
106
+ Nuxt, SvelteKit, Remix, Astro, Rails views and controllers), when it is
107
+ imported by such a file, when it is global (layouts, global styles,
108
+ dependencies; i18n messages of one locale keep the walk in that locale), when
109
+ it is the step's script or the step changed in the scenario, or when it
110
+ matches the step's `affects:` globs. Steps on the main path before a selected
111
+ step are walked first (`--no-upstream` skips them); steps with
112
+ `affects: always` (sign-in, consent) are always walked. Files nothing maps are
113
+ listed as unmapped: add `affects:` to the steps they shape, or pass
114
+ `--if-unmapped all` to walk everything then. Changes to tests, docs and CI are
115
+ ignored.
116
+
117
+ ```yaml
118
+ - id: checkout
119
+ path: /checkout
120
+ affects: [lib/payments/**, src/components/PriceSummary.tsx]
121
+ - id: consent
122
+ affects: always
123
+ ```
124
+
125
+ Report the selection with the run: which steps were walked and why, and that
126
+ the rest was not walked (or carried from which run).
127
+
128
+ ## Several locales at once
129
+
130
+ Locales are independent, so `walk --concurrency N` walks N of them at the same
131
+ time, each in its own browser context (a new visitor per locale). In an own
132
+ browser (`--ephemeral`, CI) the default follows the CPU (up to 4); on the
133
+ shared browser it stays one at a time unless you ask, because people may rely
134
+ on its signed-in tabs. Each locale's lines are printed together, in locale
135
+ order. Set `walk.concurrency` in the config for the project's default.
136
+ Viewports of one step are still captured one after another on the same page.
137
+
138
+ ## Selectors that moved
139
+
140
+ When a step script waits in vain for a selector (the button lost its id, the
141
+ class was renamed), the walk proposes a replacement from the page as it is
142
+ now: a test id, then role and accessible name, then a stable id, then the text,
143
+ preferring the element the old selector matched in the step's previous
144
+ capture. It prints the reason and a patch of the step script. Review it; if it
145
+ is the same element, `kaloko walk --steps <id> --heal` runs the step with the
146
+ patched script and writes the patch only when the step passes. Applying a heal
147
+ is fixing scenario mechanics; if the proposal points at a different element,
148
+ the product changed: report it, do not heal it. `--no-heal` skips the
149
+ proposals.
@@ -0,0 +1,66 @@
1
+ # Importing screenshots, walkthroughs and traces
2
+
3
+ Agents and test tools already leave screenshots behind: Cursor and
4
+ Antigravity walkthroughs, Claude Code screenshots, Playwright reports and
5
+ traces. `kaloko import` lays them out as a run, so they are reviewed and
6
+ signed off on the canvas like a walk.
7
+
8
+ ```bash
9
+ kaloko import shots/ # into the current run (kaloko start first)
10
+ kaloko import playwright-report/ --scenario qa/flows/checkout.yml --env staging
11
+ kaloko import test-results/checkout/trace.zip --map "click Pay=payment"
12
+ kaloko import walkthrough.md --adhoc # no scenario: an ad-hoc flow of the screens
13
+ kaloko evaluate && kaloko preview # then kaloko share, as usual
14
+ ```
15
+
16
+ Where the screens go: the current run, or a new run of `--scenario`, or with no
17
+ run (or `--adhoc`) an ad-hoc flow written to `qa/flows/import-<title>.yml`: one
18
+ manual screen per image, in order, read-only.
19
+
20
+ ## Sources
21
+
22
+ - **A folder with `steps.json`** (also `walkthrough.json`, `kaloko-import.json`):
23
+ ```json
24
+ { "title": "Checkout", "tool": "cursor",
25
+ "steps": [
26
+ { "title": "Cart", "image": "01-cart.png", "step": "cart", "url": "https://shop.test/cart",
27
+ "notes": "Two items, total 41 €", "locale": "en", "viewport": "desktop" },
28
+ { "title": "Payment", "image": "02-payment.png" }
29
+ ] }
30
+ ```
31
+ Only `image` is required. `step` names the scenario step; `viewport` and
32
+ `locale` must be in the run's scope or are chosen for you.
33
+ - **A Markdown walkthrough** (`walkthrough.md`, `README.md`, any `.md` in the
34
+ folder): every image `![alt](file.png)` in order, titled by the heading above
35
+ it, with the text between as notes. Links to `.webm`/`.mp4` are recordings.
36
+ - **A plain folder of images**: in file name order (`01-…`, `02-…`), titled by
37
+ the name. A folder of folders (Playwright `test-results/`) reads each
38
+ sub-folder as one test.
39
+ - **Playwright**: the JSON reporter's file (`--reporter=json`), an HTML report
40
+ folder (`playwright-report/`) or a `trace.zip`. Screenshot attachments become
41
+ screens; a test without them contributes its trace: one screen after each
42
+ page action (goto, click, fill, press …).
43
+
44
+ `--format folder|markdown|playwright-json|playwright-html|trace` overrides the
45
+ detection.
46
+
47
+ ## Mapping to steps
48
+
49
+ In this order: the item's `step`, `--map "Title=step,…"` (a title, group or
50
+ file name containing the label), the URL path against step paths, then the
51
+ title against step ids and titles. A second screen for the same step, locale
52
+ and viewport becomes an attachment of the step. Unmatched screens are listed
53
+ with the command that maps them; nothing is dropped silently. The viewport is
54
+ the run viewport closest to the image width (2× and 3× screenshots count by
55
+ their CSS width).
56
+
57
+ ## What an imported screen is
58
+
59
+ The image, encoded like a walked capture, with the tool and the source file.
60
+ There is no page behind it: deterministic criteria stay "not evaluated" until
61
+ the step is walked, and semantic questions are not asked without page text, so
62
+ a person decides on the canvas. Recordings are kept in the run folder
63
+ (`imported/`) and are not uploaded yet.
64
+
65
+ Report it as imported evidence, not as a walk: name the tool and say which
66
+ steps still need a real walk.
@@ -23,7 +23,7 @@ file.
23
23
  | Tool | Use it for |
24
24
  |---|---|
25
25
  | `list_runs` | published runs, newest first; filters `scenario`, `project`, `verdict`, `author`, `environment`, `branch`, `limit` |
26
- | `get_run_summary` | one run: statuses per step and locale, criteria that need attention with evidence, screenshot URLs, verdict, baseline, canvas URL, open feedback |
26
+ | `get_run_summary` | one run: statuses per step and locale, criteria that need attention with evidence (semantic ones with score and the evaluator's one-sentence `reason` per locale and viewport), regions ignored in pixel diffs and regions seen moving (`ignored_regions`, `unstable_regions`), screenshot URLs, verdict, baseline, canvas URL, open feedback |
27
27
  | `get_feedback` | run verdict with note, approved steps, unresolved rejections and comments, failed manual criteria (`run_id`, or `scenario` for its latest run) |
28
28
  | `list_notifications` | the token owner's inbox (`unread_only`, `limit`) |
29
29
  | `list_projects` | projects of the organization with counts; the slug is the `project` filter of `list_runs` and the value for `project:` in a scenario |
@@ -35,6 +35,7 @@ file.
35
35
  | `list_step_changes` | documentation layer: steps whose capture or status changed since the previous accepted run or `since` (`scenario`, `since`, `accepted`); see [documentation.md](documentation.md) |
36
36
  | `get_started` | where the organization stands (`empty`, `sample`, `active`), its sample run, the next steps and a prompt; call it in a new project, see [first-run.md](first-run.md) |
37
37
  | `add_sample_run` | adds the sample run (or returns the one there is); needs an upload or full token and the Developer / Tester role |
38
+ | `get_affected_steps` | which steps of a scenario changed files reach, with the reason per step (`scenario`, `changed_files`, `run_id`, `upstream`); route files are matched against the step paths and URLs of the newest run. Imports and `affects:` globs need the repository: `kaloko affected` follows them |
38
39
 
39
40
  ## Comment tools
40
41
 
@@ -65,6 +66,8 @@ The same data and permissions as the REST API; each tool is its REST route.
65
66
  |---|---|
66
67
  | `get_draft` | which revision each step shows, step status, who changed it (person or agent) |
67
68
  | `get_step` | the handoff: live files, signed entry URL, token set, page structure, open comments (`ref`: draft, design, vN, run id) |
69
+ | `get_step_spec` | what to build for a step as approved: elements with role, name and selector, styles mapped to tokens, states, contrast (`ref`: design by default, draft, vN, run id; `format` text or json) |
70
+ | `get_step_drift` | how an implementation run (`run`: id or `latest`) differs from the design reference, per element: expected token against the actual value |
68
71
  | `get_step_history` | versions, and revisions of a step with authors |
69
72
  | `list_step_changes` | steps that differ between two references (default design reference → draft) |
70
73
  | `get_references`, `get_tokens` | design reference and baseline; the project's token set |