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.
- package/README.md +92 -5
- package/package.json +1 -1
- package/schemas/config.v1.json +33 -0
- package/schemas/scenario.v1.json +39 -0
- package/schemas/spec.v1.json +60 -0
- package/skills/kaloko/SKILL.md +24 -3
- package/skills/kaloko/reference/acceptance.md +50 -2
- package/skills/kaloko/reference/ci.md +70 -0
- package/skills/kaloko/reference/collaboration.md +9 -1
- package/skills/kaloko/reference/design.md +35 -2
- package/skills/kaloko/reference/environments.md +5 -0
- package/skills/kaloko/reference/evaluation.md +46 -3
- package/skills/kaloko/reference/execution.md +74 -0
- package/skills/kaloko/reference/import.md +66 -0
- package/skills/kaloko/reference/mcp.md +4 -1
- package/src/cli.mjs +428 -99
- package/src/lib/affected-core.mjs +242 -0
- package/src/lib/affected.mjs +233 -0
- package/src/lib/build.mjs +30 -5
- package/src/lib/capture.mjs +43 -1
- package/src/lib/ci.mjs +207 -0
- package/src/lib/config.mjs +2 -0
- package/src/lib/design-cli.mjs +7 -3
- package/src/lib/devspec.mjs +821 -0
- package/src/lib/doctor.mjs +7 -0
- package/src/lib/drift.mjs +16 -8
- package/src/lib/evaluate.mjs +98 -14
- package/src/lib/git.mjs +6 -2
- package/src/lib/heal.mjs +207 -0
- package/src/lib/import.mjs +374 -0
- package/src/lib/init-detect.mjs +219 -0
- package/src/lib/keyboard.mjs +261 -0
- package/src/lib/manifest-core.mjs +16 -5
- package/src/lib/onboarding.mjs +15 -8
- package/src/lib/pack-help.mjs +7 -0
- package/src/lib/packs.mjs +9 -2
- package/src/lib/png.mjs +61 -0
- package/src/lib/pr.mjs +24 -2
- package/src/lib/probe.mjs +57 -0
- package/src/lib/recheck.mjs +3 -1
- package/src/lib/scenario.mjs +2 -1
- package/src/lib/service.mjs +7 -1
- package/src/lib/spec-cli.mjs +90 -0
- package/src/lib/stability-core.mjs +114 -0
- package/src/lib/stability.mjs +249 -0
- package/src/lib/unzip.mjs +31 -0
- package/src/lib/upload.mjs +114 -0
- package/src/lib/vision-core.mjs +132 -0
- package/src/lib/vision.mjs +127 -0
- package/templates/kaloko.config.yml +6 -0
- 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
|
|
14
|
-
|
|
15
|
-
`
|
|
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 `` 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 |
|