kaloko 0.3.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 +119 -0
- package/bin/kaloko.mjs +4 -0
- package/bin/qawalk.mjs +4 -0
- package/package.json +42 -0
- package/schemas/bundle.v1.json +19 -0
- package/schemas/config.v1.json +268 -0
- package/schemas/revision.v1.json +36 -0
- package/schemas/run.v1.json +549 -0
- package/schemas/scenario.v1.json +668 -0
- package/schemas/tokens.v1.json +102 -0
- package/skills/kaloko/SKILL.md +94 -0
- package/skills/kaloko/reference/acceptance.md +208 -0
- package/skills/kaloko/reference/apps.md +161 -0
- package/skills/kaloko/reference/collaboration.md +218 -0
- package/skills/kaloko/reference/design.md +143 -0
- package/skills/kaloko/reference/documentation.md +72 -0
- package/skills/kaloko/reference/environments.md +140 -0
- package/skills/kaloko/reference/evaluation.md +62 -0
- package/skills/kaloko/reference/execution.md +75 -0
- package/skills/kaloko/reference/mcp.md +69 -0
- package/skills/kaloko/reference/stacks.md +122 -0
- package/src/cli.mjs +1344 -0
- package/src/lib/access.mjs +169 -0
- package/src/lib/apps/capture.mjs +59 -0
- package/src/lib/apps/drivers.mjs +284 -0
- package/src/lib/apps/helper.swift +102 -0
- package/src/lib/apps/tree.mjs +222 -0
- package/src/lib/browser-daemon.mjs +41 -0
- package/src/lib/browser.mjs +161 -0
- package/src/lib/build.mjs +149 -0
- package/src/lib/calibrate.mjs +97 -0
- package/src/lib/capture.mjs +233 -0
- package/src/lib/compare.mjs +88 -0
- package/src/lib/config.mjs +117 -0
- package/src/lib/console.mjs +13 -0
- package/src/lib/coverage.mjs +75 -0
- package/src/lib/design-cli.mjs +440 -0
- package/src/lib/design-core.mjs +163 -0
- package/src/lib/design.mjs +164 -0
- package/src/lib/doctor.mjs +149 -0
- package/src/lib/draft.mjs +76 -0
- package/src/lib/drift.mjs +145 -0
- package/src/lib/evaluate.mjs +222 -0
- package/src/lib/git.mjs +70 -0
- package/src/lib/htmlview.mjs +130 -0
- package/src/lib/jev.mjs +95 -0
- package/src/lib/mail.mjs +182 -0
- package/src/lib/manifest-core.mjs +127 -0
- package/src/lib/pack-help.mjs +55 -0
- package/src/lib/packs.mjs +121 -0
- package/src/lib/pr.mjs +78 -0
- package/src/lib/probe.mjs +379 -0
- package/src/lib/recheck.mjs +70 -0
- package/src/lib/run.mjs +85 -0
- package/src/lib/scenario.mjs +98 -0
- package/src/lib/schema.mjs +25 -0
- package/src/lib/secrets.mjs +59 -0
- package/src/lib/service.mjs +52 -0
- package/src/lib/stack.mjs +130 -0
- package/src/lib/tokens.mjs +352 -0
- package/src/lib/util.mjs +97 -0
- package/templates/ACCEPTANCE.md +55 -0
- package/templates/cs/ACCEPTANCE.md +55 -0
- package/templates/kaloko.config.yml +76 -0
- package/templates/mail/letter-opener.mjs +47 -0
- package/templates/scenario.yml +119 -0
- package/templates/steps/consent.mjs +33 -0
- package/viewer/index.html +2772 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Collaboration: share, feedback, inbox
|
|
2
|
+
|
|
3
|
+
A run becomes useful when the people who decide can see it. The loop that
|
|
4
|
+
works for teams using Kaloko:
|
|
5
|
+
|
|
6
|
+
1. **Share the run** (`kaloko share`, tester token, after asking). The
|
|
7
|
+
command prints the canvas URL.
|
|
8
|
+
2. **Put the link where the work is tracked.** When the branch has a pull
|
|
9
|
+
request and `gh` is signed in, `kaloko share --pr` posts one comment per
|
|
10
|
+
scenario on it (summary line, canvas link, criteria that need attention
|
|
11
|
+
with evidence) and updates that same comment on every later run, so the
|
|
12
|
+
PR never fills up with Kaloko noise. Otherwise write the comment yourself:
|
|
13
|
+
what was tested (scenario, environment, locales), the summary line
|
|
14
|
+
(`n/m steps passed`), every failing or `needs_review` criterion with
|
|
15
|
+
evidence, and the canvas URL. Reviewers accept, return or comment on the
|
|
16
|
+
canvas.
|
|
17
|
+
When the organization connected the Kaloko GitHub App (Settings →
|
|
18
|
+
Integrations), the same share also creates a check on the pull request
|
|
19
|
+
that waits for review and turns green or red with the verdict; do not
|
|
20
|
+
report it as passed before a person accepted the run.
|
|
21
|
+
3. **Read feedback before continuing.** `kaloko feedback` lists the run
|
|
22
|
+
verdict, open rejections and comments, and failed manual criteria.
|
|
23
|
+
`kaloko inbox` lists what needs your attention across runs: mentions,
|
|
24
|
+
returned runs, rejected steps in your runs, new runs of scenarios you
|
|
25
|
+
reviewed, and expiry warnings. Both take `--json`; `kaloko inbox --read`
|
|
26
|
+
marks the shown items read.
|
|
27
|
+
4. **Work through the comments, then close them.** See *Processing
|
|
28
|
+
feedback* below.
|
|
29
|
+
5. **A returned run means fix, then a new run.** Runs are immutable; never
|
|
30
|
+
patch a shared run. Start a new one on the same scenario, share it and
|
|
31
|
+
reply in the tracker with the new link. The reviewer who returned it is
|
|
32
|
+
told about the new run automatically.
|
|
33
|
+
|
|
34
|
+
## Processing feedback
|
|
35
|
+
|
|
36
|
+
Comments are threads in three places:
|
|
37
|
+
|
|
38
|
+
- **A step:** optionally pinned to a position on the screenshot
|
|
39
|
+
(`pin: {x, y}` as fractions, per viewport) or to an element of a live
|
|
40
|
+
design step (`anchor`).
|
|
41
|
+
- **The whole run:** `node_id` is `''`.
|
|
42
|
+
- **The whole flow:** these stay across runs, e.g. "add the empty-cart
|
|
43
|
+
state".
|
|
44
|
+
|
|
45
|
+
`kaloko feedback` (or MCP `get_feedback` / `list_comments`) shows the open
|
|
46
|
+
ones with their ids and replies. A comment written by an agent carries the
|
|
47
|
+
agent's name (`KALOKO_AGENT`, e.g. `claude-code`), so people can tell who
|
|
48
|
+
said what.
|
|
49
|
+
|
|
50
|
+
The loop, for every open thread:
|
|
51
|
+
|
|
52
|
+
1. **Understand it.** Open the canvas link when a pin or an element
|
|
53
|
+
matters; the position is on the screenshot of that viewport and locale.
|
|
54
|
+
2. **Fix it** in the code or the scenario. When the comment asks for a
|
|
55
|
+
change of intent (criteria, scope), ask the person first.
|
|
56
|
+
3. **Answer and close.** Use
|
|
57
|
+
`kaloko comment --resolve <id> --note "Fixed in <commit>: <what changed>"`
|
|
58
|
+
(add `--flow` for flow comments; MCP `resolve_comment` takes the same
|
|
59
|
+
`note`). The closing note is a reply in the thread, and the author is
|
|
60
|
+
told in their inbox.
|
|
61
|
+
4. **When you disagree or need a decision,** reply with
|
|
62
|
+
`kaloko comment --reply <id> --note "…"` and leave the thread open.
|
|
63
|
+
Mention the person with `@name` when they must act; mentions are mailed
|
|
64
|
+
at once.
|
|
65
|
+
5. **Share a new run** once the fixes are in, and link it in the tracker.
|
|
66
|
+
Resolved threads stay visible under "Resolved" on the canvas.
|
|
67
|
+
|
|
68
|
+
Rules:
|
|
69
|
+
|
|
70
|
+
- Never resolve a thread you did not address.
|
|
71
|
+
- Never delete other people's comments; the service refuses anyway.
|
|
72
|
+
- Your own comment may be edited (`--edit <id>`) or deleted (`--delete <id>`).
|
|
73
|
+
- A rejected step (`status: rejected`) is feedback like any other: fix it,
|
|
74
|
+
resolve it, share again.
|
|
75
|
+
|
|
76
|
+
People see open counts next to flows and runs in the app, on map nodes and
|
|
77
|
+
index rows, and in the canvas's *Comments* panel (`#comments=all|run|flow`
|
|
78
|
+
in a link). Mails:
|
|
79
|
+
|
|
80
|
+
- **Right away:** mentions, rejected steps, returned runs and runs waiting
|
|
81
|
+
for approval.
|
|
82
|
+
- **In the digest:** new comments, replies, resolutions and new runs, as a
|
|
83
|
+
daily or weekly mail grouped by flow.
|
|
84
|
+
|
|
85
|
+
## Presenting a run
|
|
86
|
+
|
|
87
|
+
For stakeholders who do not read canvases, open the run in **Replay**
|
|
88
|
+
(button in the top bar, key `R`, or `#replay=1` in the URL): one step at a
|
|
89
|
+
time with its screenshot, purpose and criteria, a single *Next* action, and a
|
|
90
|
+
choice of branch at every decision node. `#replay=1&step=<id>&path=a,b,c`
|
|
91
|
+
deep-links a specific path, so an issue comment can point at "the sign-in
|
|
92
|
+
branch, step 3". Replay reads the manifest only; nothing is uploaded.
|
|
93
|
+
|
|
94
|
+
For people who work through a list rather than a flow (QA leads, content
|
|
95
|
+
and SEO teams, big runs), switch the canvas to **Index**. Use *Map | Index*
|
|
96
|
+
in the top bar, the key `I`, or `#mode=index` in the URL.
|
|
97
|
+
|
|
98
|
+
- **Rows:** every step in flow order, grouped by section. Each row shows
|
|
99
|
+
a thumbnail, status, passed criteria, failing criteria, HTTP status and
|
|
100
|
+
console errors.
|
|
101
|
+
- **Filtering:** by status, plus search over titles, paths and criteria.
|
|
102
|
+
The search also reaches the pages inside stacks.
|
|
103
|
+
- **Stacks:** a stack step is a folder. Opening it shows its page index
|
|
104
|
+
with a breadcrumb back to the run.
|
|
105
|
+
- **Navigation:** the sidebar selects rows, and the lightbox's previous and
|
|
106
|
+
next follow the filtered list.
|
|
107
|
+
- **Export:** CSV of the rows.
|
|
108
|
+
- **Links:** `#mode=index&step=<stack>` links straight into a folder.
|
|
109
|
+
|
|
110
|
+
## Public runs
|
|
111
|
+
|
|
112
|
+
An admin can make one run per scenario **public** (canvas report → *Make
|
|
113
|
+
public*, or `kaloko public --run <id>`): readable without sign-in, reviewer
|
|
114
|
+
names hidden, embeddable in an iframe. Use it for demos, status pages or
|
|
115
|
+
sharing with people outside the organization, and only for scenarios that
|
|
116
|
+
show no personal data. A tester token may later move the flag to a newer run
|
|
117
|
+
of that scenario, which is how a scheduled demo refresh works.
|
|
118
|
+
|
|
119
|
+
## Staying informed without the app
|
|
120
|
+
|
|
121
|
+
Members choose in Settings → Profile a daily or weekly e-mail digest of
|
|
122
|
+
their unread inbox and whether to get an immediate mail when their run is
|
|
123
|
+
returned or a step rejected; every mail has an unsubscribe link. Admins can
|
|
124
|
+
connect one Slack channel (Settings → Integrations, "Add to Slack") that
|
|
125
|
+
receives new shared runs, rejected steps and run verdicts. None of this
|
|
126
|
+
changes what agents do: share the run, post the link, read the feedback.
|
|
127
|
+
|
|
128
|
+
## Mentions
|
|
129
|
+
|
|
130
|
+
`@name` in a comment or verdict note notifies that colleague in the app
|
|
131
|
+
(the part of their e-mail before `@`, e.g. `@anna` or `@anna.novak`; a full
|
|
132
|
+
e-mail works too). Use it when a step needs a decision from a specific person
|
|
133
|
+
(design, legal, product owner) instead of asking in chat.
|
|
134
|
+
|
|
135
|
+
## Verdicts and baselines
|
|
136
|
+
|
|
137
|
+
- Reviewers set a **run verdict**: accepted, returned (with a note) or
|
|
138
|
+
pending. Testers see the note in `kaloko feedback` and in the inbox.
|
|
139
|
+
- An accepted run may be the scenario's **baseline**. Later runs compare
|
|
140
|
+
against it; report differences against the baseline, not only against the
|
|
141
|
+
previous run.
|
|
142
|
+
- `kaloko compare [--run <id>] [--baseline <id>] [--json]` prints the text
|
|
143
|
+
diff (step statuses, criterion verdicts, scores, evidence) of the current
|
|
144
|
+
run against the baseline, or the previous run when there is no baseline.
|
|
145
|
+
Put the relevant lines in the issue comment. On the canvas the same
|
|
146
|
+
comparison is the **Compare** selector in the top bar (or `#cmp=<run>` in
|
|
147
|
+
the URL): pixel differences per step, changed criteria, and a side-by-side
|
|
148
|
+
or diff view in the lightbox. Pixel diffs are computed in the browser;
|
|
149
|
+
nothing is uploaded.
|
|
150
|
+
- **Manual criteria** are decided on the canvas by a reviewer; treat a
|
|
151
|
+
reviewer's `fail` like a failing deterministic check.
|
|
152
|
+
- Admins may name **required approvers** per scenario (Settings). Such a
|
|
153
|
+
run stays `pending` until every one of them approved; `kaloko feedback`
|
|
154
|
+
prints `awaiting approval from: …`, so do not treat a single approval as
|
|
155
|
+
acceptance there.
|
|
156
|
+
|
|
157
|
+
## Cleaning up runs
|
|
158
|
+
|
|
159
|
+
Re-running a scenario after every fix is expected, and it fills the list: the
|
|
160
|
+
scenario list (the organization home) shows one row per scenario, and `/runs`
|
|
161
|
+
shows the newest run per scenario with "+ N older" unless a filter is set.
|
|
162
|
+
Clean up so the history stays readable; everything goes to the trash, which
|
|
163
|
+
can be restored until it is purged.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npx kaloko runs # newest run per scenario, "+ N older"
|
|
167
|
+
npx kaloko runs --scenario TASK-1273-cart # every run of one scenario
|
|
168
|
+
npx kaloko trash <run-id>... # soft delete (uploader or admin); kaloko restore <run-id>
|
|
169
|
+
npx kaloko prune --scenario TASK-1273-cart --keep 3 # dry run: lists what would go
|
|
170
|
+
npx kaloko prune --scenario TASK-1273-cart --keep 3 --yes # ask first
|
|
171
|
+
npx kaloko keep <run-id> # never expires, never pruned (--off to undo)
|
|
172
|
+
npx kaloko archive TASK-1273-klub # retired scenario, ask first (admin); --undo
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
- **Without asking:** trash runs you uploaded in this session that were
|
|
176
|
+
superseded before anyone looked at them (debug rounds without comments or a
|
|
177
|
+
verdict), and a dry-run `prune`.
|
|
178
|
+
- **Ask first:** `prune --yes`, trashing someone else's run, archiving a
|
|
179
|
+
scenario.
|
|
180
|
+
- **Never:** trash an accepted run, a baseline, a run with review comments, or a
|
|
181
|
+
run linked from an open PR or issue comment. `prune` already keeps kept,
|
|
182
|
+
accepted, baseline, design-reference and commented runs, and without the admin
|
|
183
|
+
role it trashes only your own runs.
|
|
184
|
+
- After splitting or renaming a scenario, propose archiving the old one
|
|
185
|
+
(`archived: true` in its file, or `kaloko archive <id>`). `kaloko validate`
|
|
186
|
+
warns when the service still lists a scenario whose file is gone.
|
|
187
|
+
- Report clean-ups in the tracker next to the run links: which runs went to the
|
|
188
|
+
trash and why.
|
|
189
|
+
|
|
190
|
+
An organization admin can turn on automatic clean-up after each share in
|
|
191
|
+
Settings → Storage (keep the newest N per scenario and environment).
|
|
192
|
+
|
|
193
|
+
## API for agents and CI
|
|
194
|
+
|
|
195
|
+
Everything above is available over the API with an organization token:
|
|
196
|
+
|
|
197
|
+
- `GET /api/v1/orgs/<org>/feedback?run=<id|latest>[&scenario=<id>]`
|
|
198
|
+
- `GET|POST /api/v1/orgs/<org>/runs/<id>/comments` (a step: `node_id`;
|
|
199
|
+
the whole run: `node_id: ""`), `GET|POST …/scenarios/<id>/comments`
|
|
200
|
+
(the whole flow), and per comment `PATCH`, `DELETE`, `POST …/<cid>/resolve`
|
|
201
|
+
(with `note`) and `…/<cid>/reopen`; `GET /api/v1/orgs/<org>/comments?state=open|all&scenario=&run=&mine=1`
|
|
202
|
+
across the organization. Lists of runs and scenarios carry `open_comments`.
|
|
203
|
+
- `GET /api/v1/orgs/<org>/notifications[?unread=1]`, `POST` with
|
|
204
|
+
`{"read": "all"}` or `{"read": [ids]}`
|
|
205
|
+
- `GET /api/v1/orgs/<org>/runs[?project=&scenario=&kind=&verdict=&author=&environment=&branch=&q=][&latest=1]`
|
|
206
|
+
(`latest=1`: the newest run per scenario with `older`), `GET /api/v1/orgs/<org>/runs/<id>`
|
|
207
|
+
- Clean-up: `DELETE …/runs/<id>` (trash), `POST …/runs/<id>/restore`,
|
|
208
|
+
`POST …/runs/<id>/keep` with `{"keep": true|false}`,
|
|
209
|
+
`POST /api/v1/orgs/<org>/runs/prune` with `{ scenario?, project?, environment?, keep_latest: 3, older_than_days?, dry_run: true }`
|
|
210
|
+
(answers `trash` and `kept` with reasons), `POST …/scenarios/<id>/archive`
|
|
211
|
+
and `…/unarchive` (admin)
|
|
212
|
+
- `GET /api/v1/orgs/<org>/runs/<id>/export.zip` (`kaloko export`): the whole
|
|
213
|
+
run as a zip before it expires; keep it with the issue when the evidence
|
|
214
|
+
must outlive the retention period.
|
|
215
|
+
- MCP server for agents: see [mcp.md](mcp.md).
|
|
216
|
+
|
|
217
|
+
Read-only tokens may list but not change anything; keep CI tokens read-only
|
|
218
|
+
unless the job publishes runs.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Design with Kaloko
|
|
2
|
+
|
|
3
|
+
Kaloko hosts designs as live HTML steps of the same scenario that development and QA use. You design with
|
|
4
|
+
whatever skill, model and style the person uses; Kaloko keeps the draft, the versions, the comments and the
|
|
5
|
+
design reference, and checks the implementation against it. This reference says how to fit your work into
|
|
6
|
+
that. It says nothing about how a design should look.
|
|
7
|
+
|
|
8
|
+
## Design environments
|
|
9
|
+
|
|
10
|
+
A design environment is a folder the CLI serves while it walks:
|
|
11
|
+
|
|
12
|
+
```yaml
|
|
13
|
+
# kaloko.config.yml
|
|
14
|
+
environments:
|
|
15
|
+
design: { kind: design, serve: design }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`kaloko start --scenario qa/flows/checkout.yml --env design` starts a run of it. The scenario is the one the
|
|
19
|
+
implementation uses: same step ids, same criteria. Design steps meet the acceptance criteria too (headings,
|
|
20
|
+
labels, semantic questions), so a design is accepted before anyone builds it. Checks against the design
|
|
21
|
+
reference (`design_pixels`, `design_structure`) are left out on a design environment.
|
|
22
|
+
|
|
23
|
+
## The bundle
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
design/
|
|
27
|
+
tokens.json token set (W3C DTCG), optional
|
|
28
|
+
_shared/app.css shared files: fonts, styles, images, scripts
|
|
29
|
+
cart/index.html one folder per step id
|
|
30
|
+
cart/cs/index.html optional override for a locale
|
|
31
|
+
payment/index.html
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- Plain HTML, CSS, JS and assets only (`qawalk.bundle.v1`: html, css, js, mjs, json, svg, woff2, woff, png,
|
|
35
|
+
jpg, webp, avif, gif, mp4, webm, txt). No build step on the service side: build locally, keep the output.
|
|
36
|
+
- A step's revision is its page, the files next to it and everything its page references (stylesheets,
|
|
37
|
+
images, fonts, module imports, `fetch('./fixtures/x.json')`). Links to other steps are not files it needs.
|
|
38
|
+
- Live steps run sandboxed on their own origin with `connect-src 'self'`: no real APIs. Use JSON fixtures in
|
|
39
|
+
the bundle.
|
|
40
|
+
- Prototype links: `<a data-qawalk-go="payment">` moves the canvas to that step, whatever the `href` says.
|
|
41
|
+
- Reference token values as CSS custom properties (`var(--color-accent)`), so the inspector and the token
|
|
42
|
+
check see where values come from.
|
|
43
|
+
|
|
44
|
+
## Sync and publish
|
|
45
|
+
|
|
46
|
+
- `kaloko walk` renders only revisions whose captures are missing (same files, same capture).
|
|
47
|
+
- `kaloko status` shows each step: synced, changed here, changed in the draft, conflict; and its step status.
|
|
48
|
+
- `kaloko sync` saves your changed steps into the shared draft and takes steps others changed. A step changed
|
|
49
|
+
on both sides is a conflict: name it with `--mine <step>` or `--theirs <step>`; never delete to resolve.
|
|
50
|
+
- `kaloko share` on a design environment publishes a version of the flow (`v4 · 3 changed, 17 unchanged`).
|
|
51
|
+
A version counts as a shared run. Publish when the person asks, not after every change.
|
|
52
|
+
- Step status (`in progress`, `ready for review`, `ready for dev`) is set in the canvas or with MCP
|
|
53
|
+
`set_step_status`; `ready for dev` notifies followers.
|
|
54
|
+
- Set `KALOKO_AGENT=<your name>` so people see your writes as yours in presence, history and audit.
|
|
55
|
+
|
|
56
|
+
## The loop
|
|
57
|
+
|
|
58
|
+
1. Design or change steps in the folder with the person's design skill.
|
|
59
|
+
2. `kaloko walk` (and `kaloko evaluate` if the step has semantic criteria), `kaloko sync`.
|
|
60
|
+
3. Read `kaloko feedback` on the design environment: open comments, pinned ones with their element
|
|
61
|
+
(`on main > label`). People comment in the canvas; they may be looking right now.
|
|
62
|
+
4. Change what the comments ask, sync again, then answer in the comment thread (MCP `add_draft_comment`).
|
|
63
|
+
5. When the person is happy, `kaloko share --name "…"` publishes a version.
|
|
64
|
+
|
|
65
|
+
## References
|
|
66
|
+
|
|
67
|
+
- The design reference is an accepted version: `kaloko reference --design --version 4` (a person accepts the
|
|
68
|
+
version first; ask before setting a reference).
|
|
69
|
+
- The baseline stays the last good implementation run: `kaloko reference --baseline --run <id>`.
|
|
70
|
+
- Changing the design reference changes what implementation runs are checked against: tell the team.
|
|
71
|
+
|
|
72
|
+
## Handoff
|
|
73
|
+
|
|
74
|
+
Development builds from the design reference:
|
|
75
|
+
|
|
76
|
+
- `kaloko export --live [--version n] --out design/` writes the live files into a folder.
|
|
77
|
+
- MCP `get_step` (scenario, step, `ref: design`) returns the file list, a signed entry URL, the token set, the
|
|
78
|
+
page structure and open comments; `list_step_changes` names the steps that changed since the last reference.
|
|
79
|
+
- Translate to the project's stack with the project's own skills; keep the step ids and the token names.
|
|
80
|
+
|
|
81
|
+
## Tokens
|
|
82
|
+
|
|
83
|
+
- The set is W3C DTCG. Both value styles are read: strings (`"#2E6BFF"`, `"16px"`) and the current format's
|
|
84
|
+
objects (`{ "colorSpace": "srgb", "components": [...], "hex": "#2e6bff" }`, `{ "value": 16, "unit": "px" }`),
|
|
85
|
+
composite types (typography, shadow, border, transition, gradient), aliases `{group.token}` and
|
|
86
|
+
`{ "$ref": "#/json/pointer" }`, `$extends`, `$root` and `$deprecated`. New sets: prefer the object values.
|
|
87
|
+
- Modes (light, dark): a DTCG resolver `design/tokens.resolver.json` (sets plus a `theme` modifier whose
|
|
88
|
+
contexts point at files) wins over `tokens.json`; `push` inlines its files. Older sets with top-level
|
|
89
|
+
`light`/`dark` groups still work. `tokens_mode` in the environment picks the mode the checks use.
|
|
90
|
+
- `kaloko tokens validate` reports names with `{`, `}` or `.`, references that point nowhere and values that
|
|
91
|
+
cannot be read; `push` refuses a set with problems, so does the service.
|
|
92
|
+
- `kaloko tokens push` stores the set as the project's next token set version; `pull` gets it.
|
|
93
|
+
- `kaloko tokens check` lists raw colors, fonts, sizes, spacing and radii in the design folder that are not in
|
|
94
|
+
the set, with the nearest token; a value that only a deprecated token has is named with its note.
|
|
95
|
+
|
|
96
|
+
## Checking implementation
|
|
97
|
+
|
|
98
|
+
Turn on `packs: [design]` (usually `[design, a11y]`) for the steps in the implementation scenario:
|
|
99
|
+
|
|
100
|
+
| Id | Checks |
|
|
101
|
+
|---|---|
|
|
102
|
+
| AC801 | pixels: under 3 % differ from the design reference (same algorithm as the canvas) |
|
|
103
|
+
| AC802 | structure: headings, landmarks, actions and form fields as in the reference |
|
|
104
|
+
| AC803 | tokens: authored colors, fonts, sizes, spacing and radii come from the token set |
|
|
105
|
+
|
|
106
|
+
Contrast and the other accessibility basics come from the `a11y` pack: `packs: [design, a11y]`.
|
|
107
|
+
|
|
108
|
+
`kaloko evaluate` fetches the design reference (of the design branch linked to the git branch, if any) and
|
|
109
|
+
fills the checks. Findings name what differs and the token to use; fix the implementation, not the reference.
|
|
110
|
+
|
|
111
|
+
## Canvas edits
|
|
112
|
+
|
|
113
|
+
People can change a step's text and assign tokens in the canvas inspector. Each edit is a new revision; a file
|
|
114
|
+
shared by several locales changes for all of them. `kaloko sync` pulls the edit into the folder as a
|
|
115
|
+
`<style data-qawalk-edits>` block and changed text: fold the rules into the real stylesheet when you next touch
|
|
116
|
+
the step, then sync.
|
|
117
|
+
|
|
118
|
+
## Branches
|
|
119
|
+
|
|
120
|
+
- `kaloko branch create redesign --git feat/redesign` starts a branch of the draft; `--from v4` starts from a
|
|
121
|
+
version. Work on it with `--branch redesign` on `sync`, `status` and `share`.
|
|
122
|
+
- The folder mirrors one branch at a time; switching (`kaloko sync --branch main`) takes that branch's steps
|
|
123
|
+
and never pushes the other branch into it.
|
|
124
|
+
- Merging is the person's decision: `kaloko branch merge redesign`; steps changed on both sides need
|
|
125
|
+
`--take-branch <step>` or `--keep-main <step>`.
|
|
126
|
+
|
|
127
|
+
## HTML view
|
|
128
|
+
|
|
129
|
+
Experimental, Business plan. `html_view: true` on an app environment keeps a static, script-free copy of each
|
|
130
|
+
captured page (secrets and hidden values removed) that opens in the canvas like a live step, so the inspector
|
|
131
|
+
works on the real product. It is refused on production pages behind a sign-in. `kaloko export --live --views
|
|
132
|
+
--run <id> --out design/` turns those copies into design steps: a redesign that starts from the product.
|
|
133
|
+
|
|
134
|
+
## Bring your own design skill
|
|
135
|
+
|
|
136
|
+
Any skill works if it writes the bundle layout above:
|
|
137
|
+
|
|
138
|
+
- a design skill of Claude or another agent: ask it to write `design/<step>/index.html` per scenario step and
|
|
139
|
+
shared files into `design/_shared/`;
|
|
140
|
+
- a brand or design-system skill: have it produce `tokens.json` and the shared CSS;
|
|
141
|
+
- a Figma export through the person's own tooling (for example a Figma MCP server): convert frames to HTML
|
|
142
|
+
per step, then walk and sync;
|
|
143
|
+
- hand-written HTML is fine.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Documentation from runs
|
|
2
|
+
|
|
3
|
+
A run is also a library of reference captures: every step, locale and
|
|
4
|
+
viewport has a screenshot and the HTML. On the Business plan the service
|
|
5
|
+
gives each step a stable address, lists what changed, and calls you when a
|
|
6
|
+
run is accepted, so a manual, a course or product documentation can be
|
|
7
|
+
rebuilt from the newest accepted run instead of screenshotting by hand.
|
|
8
|
+
|
|
9
|
+
## Prepare the run
|
|
10
|
+
|
|
11
|
+
- Walk the scenario as usual and let a person accept the run on the canvas;
|
|
12
|
+
documentation should come from accepted (or baseline) runs only.
|
|
13
|
+
- Tag the release (`git tag v2.4.0`) before `kaloko start`, or pass
|
|
14
|
+
`--app-version 2.4.0`; the version lands in the manifest as `app_version` and in every
|
|
15
|
+
latest-capture answer, so the documentation can say which version it shows.
|
|
16
|
+
- Accepted and baseline runs do not expire on Business and Enterprise.
|
|
17
|
+
|
|
18
|
+
## Stable URLs
|
|
19
|
+
|
|
20
|
+
With an organization token (`Authorization: Bearer qwk_…`, a read-only
|
|
21
|
+
viewer token is enough):
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
GET /api/v1/orgs/<org>/scenarios/<scenario>/steps step index with links
|
|
25
|
+
GET /api/v1/orgs/<org>/scenarios/<scenario>/steps/<step>/latest.json metadata (run with app_version, captured_at, page URL, size)
|
|
26
|
+
GET /api/v1/orgs/<org>/scenarios/<scenario>/steps/<step>/latest.image the screenshot (latest.webp or latest.png when you know the format)
|
|
27
|
+
GET /api/v1/orgs/<org>/scenarios/<scenario>/steps/<step>/latest.html the captured HTML (served sandboxed)
|
|
28
|
+
GET /api/v1/orgs/<org>/scenarios/<scenario>/changes steps changed since the previous accepted run
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Add `?locale=cs&viewport=desktop` (defaults: the run's first locale and
|
|
32
|
+
viewport) and `&accepted=1` to use the newest accepted run instead of the
|
|
33
|
+
newest run. Files answer with an `ETag`; send `If-None-Match` and a 304 means
|
|
34
|
+
nothing to download.
|
|
35
|
+
|
|
36
|
+
## Only rebuild what changed
|
|
37
|
+
|
|
38
|
+
`changes` (MCP `list_step_changes`) compares the newest run with the previous
|
|
39
|
+
accepted one, or with `?since=<run id>`. A step is listed when it is new, its
|
|
40
|
+
image bytes differ, or its status changed; `removed` lists steps that are
|
|
41
|
+
gone. Timestamps or animations make a page count as changed, so keep
|
|
42
|
+
captures stable (fixed test data, no clocks on screen) for documentation
|
|
43
|
+
scenarios.
|
|
44
|
+
|
|
45
|
+
## Webhooks
|
|
46
|
+
|
|
47
|
+
Settings → Integrations → Webhooks (admin): an https URL and the events
|
|
48
|
+
`run.accepted` and/or `run.shared`. Each call is a JSON POST
|
|
49
|
+
`{ id, type, created_at, org, data: { run, steps, steps_url, changes_url } }`
|
|
50
|
+
with `QAwalk-Signature: t=<unix time>,v1=<hex HMAC-SHA256 of "<t>.<body>">`
|
|
51
|
+
signed with the webhook's secret (copy it from Settings). Verify the
|
|
52
|
+
signature and the time (reject older than 5 minutes), answer 2xx within 5
|
|
53
|
+
seconds, and do the work asynchronously. Also over the API:
|
|
54
|
+
`GET|POST /api/v1/orgs/<org>/webhooks`, `DELETE …/webhooks/<id>`.
|
|
55
|
+
|
|
56
|
+
## Export into a folder
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx kaloko export --scenario checkout --accepted --out docs/assets/checkout
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
writes `steps/<step>/<locale>/<viewport>.<ext>` and `.html` plus
|
|
63
|
+
`index.json` (run with app_version, captured_at, page URL per file). Run it again and
|
|
64
|
+
files from an unchanged run are kept, so a documentation repository sees only
|
|
65
|
+
real changes. `examples/docs-pipeline.mjs` in the Kaloko repository shows a
|
|
66
|
+
complete loop that rebuilds a Markdown manual and touches only changed steps.
|
|
67
|
+
|
|
68
|
+
## Done means
|
|
69
|
+
|
|
70
|
+
The manual or course references the exported files (or the stable URLs), says
|
|
71
|
+
which application version it shows, and a re-run after a new accepted run
|
|
72
|
+
changes only the pages of steps listed by `changes`.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Environments
|
|
2
|
+
|
|
3
|
+
Profiles live in `kaloko.config.yml` under `environments`. The CLI enforces
|
|
4
|
+
them; do not work around a block.
|
|
5
|
+
|
|
6
|
+
- `local`, `review`, `staging`: you may create the test data a scenario
|
|
7
|
+
needs (users with roles, carts, orders in test payment mode).
|
|
8
|
+
- `production`: always readonly, regardless of config. Only scenarios with
|
|
9
|
+
`readonly: true`, as an ordinary visitor or customer. No admin, no sign-in
|
|
10
|
+
to back offices, no data creation, no orders. Typical: SEO checks, landing
|
|
11
|
+
pages, checkout up to payment.
|
|
12
|
+
|
|
13
|
+
Test data preparation for review and staging belongs to the project's CI
|
|
14
|
+
prepare step; assume it exists and create only what the scenario itself needs.
|
|
15
|
+
|
|
16
|
+
## Who does what
|
|
17
|
+
|
|
18
|
+
Kaloko needs evidence in its format: captures of screens and e-mails in a run.
|
|
19
|
+
How you get to them depends on the project's stack, and that part is yours.
|
|
20
|
+
|
|
21
|
+
- **The CLI handles the standards**: HTTP Basic and header tokens in front of
|
|
22
|
+
an environment, client certificates, a saved browser session, the readonly
|
|
23
|
+
policy, Mailpit, and e-mails as `.eml`, `.html`, `.json` or `.txt`.
|
|
24
|
+
- **You arrange the rest for this project** with its own tools and common
|
|
25
|
+
practice: how test users are created and signed in, where the application's
|
|
26
|
+
e-mails end up, how a review app's URL is known. Write that down once in the
|
|
27
|
+
project (config, step scripts, a mail adapter, a project skill) so the next
|
|
28
|
+
run does not rediscover it.
|
|
29
|
+
- **You ask the person** for secret values and for anything only a person can
|
|
30
|
+
do (an SSO or MFA sign-in, VPN access, a new test account in a system you
|
|
31
|
+
cannot reach).
|
|
32
|
+
|
|
33
|
+
## Access to an environment
|
|
34
|
+
|
|
35
|
+
Three layers, each in its own place:
|
|
36
|
+
|
|
37
|
+
| Layer | Examples | Where |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| Gate in front of the whole environment | HTTP Basic, Cloudflare Access service token, Vercel protection bypass, a custom header, mutual TLS | `environments.<env>.access` |
|
|
40
|
+
| Sign-in to the application | form login, SSO/OAuth, MFA/TOTP | scenario `sessions` + `environments.<env>.accounts` + step scripts |
|
|
41
|
+
| Network | VPN, IP allowlist | not config: the machine running the agent must have access; say so when it does not |
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
environments:
|
|
45
|
+
staging:
|
|
46
|
+
base_url: https://staging.example.com
|
|
47
|
+
access:
|
|
48
|
+
origins: [https://staging.example.com, https://api.staging.example.com] # default: base_url origins
|
|
49
|
+
basic: { user_env: STAGING_USER, password_env: STAGING_PASSWORD }
|
|
50
|
+
headers:
|
|
51
|
+
CF-Access-Client-Id: { env: CF_ACCESS_CLIENT_ID }
|
|
52
|
+
CF-Access-Client-Secret: { env: CF_ACCESS_CLIENT_SECRET }
|
|
53
|
+
client_certificate: { cert_file: certs/qa.pem, key_env: QA_CLIENT_KEY }
|
|
54
|
+
accounts:
|
|
55
|
+
member: { user: member@example.test, password_env: STAGING_MEMBER_PASSWORD }
|
|
56
|
+
admin: { user_env: STAGING_ADMIN_USER, password_env: STAGING_ADMIN_PASSWORD, totp_env: STAGING_ADMIN_TOTP }
|
|
57
|
+
sso: {}
|
|
58
|
+
review:
|
|
59
|
+
base_url: https://${REVIEW_HOST} # review apps: CI provides the variable
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Rules:
|
|
63
|
+
|
|
64
|
+
- Secrets never go into `kaloko.config.yml`, a scenario or a step script.
|
|
65
|
+
Every `*_env` and `{ env: NAME }` names a variable; the values live in the
|
|
66
|
+
environment, the project `.env` (ignored by git) or `~/.config/kaloko/.env`.
|
|
67
|
+
Choose names that fit the project; ask the person for the values.
|
|
68
|
+
- The gate is sent only to `access.origins`, never to third parties (analytics,
|
|
69
|
+
CDNs, payment providers). List an API on another host explicitly;
|
|
70
|
+
`https://*.example.com` covers subdomains.
|
|
71
|
+
- The CLI applies the gate and the readonly policy to every browser context it
|
|
72
|
+
creates: the shared browser, `walk` sessions and one-off captures. A context
|
|
73
|
+
you create yourself over CDP does not get them; work in the shared browser's
|
|
74
|
+
default context, or use `walk`.
|
|
75
|
+
- Values the CLI knows as secrets are replaced by `[redacted]` in captured HTML,
|
|
76
|
+
page text and console entries. Screenshots are not redacted: do not capture
|
|
77
|
+
a screen that shows a secret.
|
|
78
|
+
- `kaloko doctor` checks that the variables are set, that the gate lets you in
|
|
79
|
+
(HTTP 401/403 is a failure) and that each account can sign in or has a
|
|
80
|
+
saved session.
|
|
81
|
+
|
|
82
|
+
## Accounts and sign-in
|
|
83
|
+
|
|
84
|
+
A scenario session's `account` is a key; `environments.<env>.accounts.<key>`
|
|
85
|
+
maps it to credentials in that environment. Step scripts receive them as
|
|
86
|
+
`session.credentials` (`user`, `password`, `totp()`, `storage_state`) and sign
|
|
87
|
+
in the way the application does it:
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
export default async ({ page, url, session }) => {
|
|
91
|
+
const { user, password } = session.credentials
|
|
92
|
+
await page.goto(url('sign-in'))
|
|
93
|
+
await page.fill('input[type=email]', user)
|
|
94
|
+
await page.fill('input[type=password]', password)
|
|
95
|
+
await page.click('button[type=submit]')
|
|
96
|
+
if (await page.locator('input[autocomplete=one-time-code]').isVisible()) await page.fill('input[autocomplete=one-time-code]', session.credentials.totp())
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
SSO or MFA that a script cannot pass: ask the person to run
|
|
101
|
+
`kaloko auth save --env <env> --account <key>` once. They sign in in a
|
|
102
|
+
visible browser; the session is saved under the output directory (owner-only,
|
|
103
|
+
git-ignored, never uploaded) and `walk` loads it into that account's sessions.
|
|
104
|
+
When the application asks for sign-in again, the session expired: ask for a
|
|
105
|
+
new `auth save`. `kaloko auth list` shows the saved sessions and their age.
|
|
106
|
+
|
|
107
|
+
Prefer, in this order: a test account the project already has for QA; a
|
|
108
|
+
seeded or API-created account on non-production environments; a saved
|
|
109
|
+
session. Never use a real person's account.
|
|
110
|
+
|
|
111
|
+
## E-mails
|
|
112
|
+
|
|
113
|
+
Flows that send e-mails need the message as an `email` step. Where the
|
|
114
|
+
message is depends on the stack:
|
|
115
|
+
|
|
116
|
+
- **Mailpit** (built in): `mail: { provider: mailpit, url, auth, address }`.
|
|
117
|
+
`auth` takes `basic` and `headers` like `access`. `address` with `{run}`
|
|
118
|
+
gives every run its own recipient, so shared mailboxes stay apart.
|
|
119
|
+
- **Anything else** (letter_opener, Mailosaur, MailSlurp, IMAP, a log, the
|
|
120
|
+
application's own API): write a small adapter and set
|
|
121
|
+
`mail: { provider: script, script: qa/mail/inbox.mjs, options: {...} }`.
|
|
122
|
+
Its default export is `async ({ to, subject, since, options, root, env })`
|
|
123
|
+
and returns the newest matching message
|
|
124
|
+
`{ id, subject, from, to: [address], date, html, text }` or `null`;
|
|
125
|
+
`kaloko mail` and `walk` poll it. The package ships an example to copy:
|
|
126
|
+
`node_modules/kaloko/templates/mail/letter-opener.mjs`.
|
|
127
|
+
- **One-off or unusual**: get the message yourself and hand it over:
|
|
128
|
+
`kaloko mail --step <id> --file message.eml` (also `.html`, `.json` with the
|
|
129
|
+
message shape, `.txt`).
|
|
130
|
+
|
|
131
|
+
`kaloko mail` and `walk` take only messages received after the run started
|
|
132
|
+
(adapters get it as `since`), so a staging mailbox that collects everyone's
|
|
133
|
+
mail cannot hand over an old message silently. `--since <ISO date>` moves the
|
|
134
|
+
boundary, `--any-time` drops it, and `--id <message id>` takes one exact
|
|
135
|
+
message (subjects repeat). The canvas shows when the message arrived and warns
|
|
136
|
+
when it predates the run.
|
|
137
|
+
|
|
138
|
+
Pick what fits the project and keep it in the project; do not change how the
|
|
139
|
+
application sends mail just for QA unless the person agrees (switching a Rails
|
|
140
|
+
app from letter_opener to SMTP locally, for example).
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Evaluation
|
|
2
|
+
|
|
3
|
+
`kaloko walk` sends the semantic questions of each step as soon as it is captured and ends with the
|
|
4
|
+
verdicts: what fails and what a person should look at, per step, locale and viewport. Use that list to fix
|
|
5
|
+
things right away. Steps captured later with `kaloko capture` need `kaloko evaluate`; it reuses every cached
|
|
6
|
+
answer, so running it again is cheap.
|
|
7
|
+
|
|
8
|
+
`kaloko evaluate` combines, per capture:
|
|
9
|
+
|
|
10
|
+
- deterministic results computed in the live page at capture time (with
|
|
11
|
+
evidence: selector snippet, measured value);
|
|
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);
|
|
16
|
+
- `manual` criteria stay `not_evaluated` until a reviewer decides.
|
|
17
|
+
|
|
18
|
+
Where the evaluator runs: with `TYPESAFE_API_KEY` set locally, your own key; without it, the organization's
|
|
19
|
+
service evaluates with its key (Team plan and up, a monthly allowance of questions; `kaloko evaluate` prints
|
|
20
|
+
"via Kaloko (340 of 1000 questions this month)"). Answers are cached by content locally and in the service, so
|
|
21
|
+
evaluating the same capture again costs nothing. `evaluators.jev.hosted: false` keeps it to your own key.
|
|
22
|
+
When neither is available, or the allowance is used up, semantic criteria stay `not_evaluated`; say so in the
|
|
23
|
+
report with the reason `kaloko evaluate` gives.
|
|
24
|
+
|
|
25
|
+
Results are cached by content hash, so re-running is cheap. The default
|
|
26
|
+
evaluator is text-only and most accurate in English; it is weak at numbers,
|
|
27
|
+
which is why those are deterministic.
|
|
28
|
+
|
|
29
|
+
When a criterion comes back `needs_review`, read the reduced state the
|
|
30
|
+
evaluator saw (`steps/<node>/<locale>/<viewport>.capture.json`, key `state`)
|
|
31
|
+
and the screenshot. Either the page is genuinely unclear (report it), the
|
|
32
|
+
reducer missed something (report a Kaloko bug), or the question is too broad
|
|
33
|
+
(narrow it with `scope`, `true`/`false`; this changes mechanics, not intent).
|
|
34
|
+
Check evidence of passing deterministic checks too: a match in the wrong
|
|
35
|
+
region (e.g. a shipping threshold instead of the product price) means the
|
|
36
|
+
selector needs a scope.
|
|
37
|
+
|
|
38
|
+
When the check itself was wrong (selector, pattern too broad) and the step
|
|
39
|
+
cannot be repeated (data created, an e-mail sent once, a state that moved
|
|
40
|
+
on), fix the scenario and run `kaloko evaluate --recheck [--steps a,b]`: the
|
|
41
|
+
deterministic checks run again against the stored HTML with page scripts off
|
|
42
|
+
and are marked `rechecked`; console errors, overflow and performance keep
|
|
43
|
+
their live result. When the page content itself is in question, capture again.
|
|
44
|
+
|
|
45
|
+
## Quick signals
|
|
46
|
+
|
|
47
|
+
Beside the criteria, every captured screen gets three cheap questions in the same evaluator request: does the
|
|
48
|
+
page do what the step's `purpose` says, is its text in the expected language, does it look broken (an error,
|
|
49
|
+
placeholder text, a blank page). They never change a verdict; the canvas marks a screen with ⚠ when one is
|
|
50
|
+
off (purpose or language at 30 % or less, broken at 70 % or more). Mention them in the report when they
|
|
51
|
+
disagree with passing criteria: it usually means a criterion is missing. `evaluators.jev.signals: false`
|
|
52
|
+
turns them off; they do not count against the hosted allowance.
|
|
53
|
+
|
|
54
|
+
## Reporting
|
|
55
|
+
|
|
56
|
+
After `kaloko build`, report: the summary line, each failing or
|
|
57
|
+
`needs_review` criterion with step, locale, viewport and evidence, blocked
|
|
58
|
+
requests if any, and the preview path. Do not claim a criterion passed when
|
|
59
|
+
it was not evaluated.
|
|
60
|
+
|
|
61
|
+
`needs_review` is not a failure: look at the screenshot and state your
|
|
62
|
+
reading, or leave it to the reviewer.
|