kaloko 0.13.0 → 0.15.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 +6 -2
- package/bin/qawalk.mjs +2 -1
- package/package.json +1 -1
- package/schemas/changelog.v1.json +5 -0
- package/schemas/config.v1.json +2 -1
- package/schemas/evidence.v1.json +257 -0
- package/schemas/run.v1.json +67 -1
- package/schemas/scenario.v1.json +34 -1
- package/skills/kaloko/SKILL.md +24 -5
- package/skills/kaloko/reference/acceptance.md +37 -28
- package/skills/kaloko/reference/apps.md +1 -1
- package/skills/kaloko/reference/ci.md +37 -10
- package/skills/kaloko/reference/collaboration.md +8 -1
- package/skills/kaloko/reference/design.md +11 -9
- package/skills/kaloko/reference/docs.md +9 -3
- package/skills/kaloko/reference/documentation.md +2 -2
- package/skills/kaloko/reference/evaluation.md +42 -1
- package/skills/kaloko/reference/evidence.md +80 -0
- package/skills/kaloko/reference/integrations.md +23 -4
- package/skills/kaloko/reference/mcp.md +13 -5
- package/skills/kaloko/reference/portable-html.md +1 -1
- package/skills/kaloko/reference/stacks.md +1 -1
- package/src/cli.mjs +265 -70
- package/src/lib/build.mjs +10 -1
- package/src/lib/capture.mjs +7 -0
- package/src/lib/changelog-core.mjs +11 -8
- package/src/lib/ci.mjs +1 -1
- package/src/lib/cli-args.mjs +11 -5
- package/src/lib/config.mjs +25 -1
- package/src/lib/docs-export.mjs +44 -10
- package/src/lib/docs.mjs +3 -2
- package/src/lib/doctor.mjs +3 -1
- package/src/lib/draft.mjs +1 -1
- package/src/lib/evaluate.mjs +7 -2
- package/src/lib/evidence-core.mjs +300 -0
- package/src/lib/health-core.mjs +205 -0
- package/src/lib/health.mjs +219 -0
- package/src/lib/integrations-cli.mjs +14 -3
- package/src/lib/jev.mjs +4 -2
- package/src/lib/legacy.mjs +28 -0
- package/src/lib/login.mjs +1 -1
- package/src/lib/manifest-core.mjs +23 -10
- package/src/lib/pack-help.mjs +53 -51
- package/src/lib/packs.mjs +67 -55
- package/src/lib/pr.mjs +2 -0
- package/src/lib/run.mjs +13 -1
- package/src/lib/service.mjs +16 -4
- package/src/lib/signoff.mjs +86 -6
- package/src/lib/util.mjs +28 -2
- package/src/lib/video-cli.mjs +2 -2
- package/templates/scenario.yml +1 -1
- package/viewer/index.html +557 -51
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ For example:
|
|
|
51
51
|
|
|
52
52
|
> Draft a Kaloko scenario for https://example.com (home, pricing, contact)
|
|
53
53
|
> with the seo, a11y and perf packs, run it on production read-only and
|
|
54
|
-
> summarise
|
|
54
|
+
> summarise its health.
|
|
55
55
|
|
|
56
56
|
## Run a scenario by hand (or in CI)
|
|
57
57
|
|
|
@@ -229,7 +229,11 @@ show (overlap, cut-off text, a raw translation key, an endless spinner);
|
|
|
229
229
|
reviewers turn the right findings into comments with one click, and findings
|
|
230
230
|
never change a verdict. Triage counts against the hosted-evaluation allowance,
|
|
231
231
|
so it needs the Team plan or higher.
|
|
232
|
-
|
|
232
|
+
Check packs (`seo`, `a11y`, `perf`, `usability`, `console`) report the app's
|
|
233
|
+
health apart from acceptance: they never fail a step that meets its brief,
|
|
234
|
+
`kaloko health` lists what is new since the previous run, and
|
|
235
|
+
`kaloko health adopt` makes one check an acceptance criterion when the team
|
|
236
|
+
wants it to decide. The `a11y` pack walks the page with Tab (order, visible focus, traps, skip
|
|
233
237
|
link) and reads names from the accessibility tree. Pixel diffs skip the
|
|
234
238
|
regions a step ignores; `kaloko walk --stability 3` and `kaloko stability`
|
|
235
239
|
find the clocks, ads and carousels worth ignoring, and `kaloko stability --pull`
|
package/bin/qawalk.mjs
CHANGED
package/package.json
CHANGED
|
@@ -57,6 +57,11 @@
|
|
|
57
57
|
"run": { "type": ["string", "null"] },
|
|
58
58
|
"version": { "type": ["string", "null"], "description": "The release the picture belongs to (null: the newest accepted)." },
|
|
59
59
|
"image": { "type": ["string", "null"] },
|
|
60
|
+
"video": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"description": "Present when the accepted run has a recording of the step and the reference does not say media=image: links like image, and the length.",
|
|
63
|
+
"properties": { "mp4": { "type": ["string", "null"] }, "webm": { "type": ["string", "null"] }, "duration_ms": { "type": ["number", "null"] } }
|
|
64
|
+
},
|
|
60
65
|
"canvas": { "type": ["string", "null"] }
|
|
61
66
|
}
|
|
62
67
|
}
|
package/schemas/config.v1.json
CHANGED
|
@@ -226,7 +226,8 @@
|
|
|
226
226
|
"serve": { "type": "string", "description": "kind: design. Folder with one sub-folder per step (<step>/index.html, optional <step>/<locale>/index.html) and shared files in _shared/; relative to the config." },
|
|
227
227
|
"fixtures": { "type": "string", "description": "kind: design. Folder of JSON fixtures live steps may fetch instead of real APIs; relative to the config." },
|
|
228
228
|
"origins": { "type": "array", "maxItems": 20, "items": { "type": "string", "pattern": "^https://(\\*\\.)?[A-Za-z0-9.-]+(:[0-9]{1,5})?/?$" }, "description": "kind: design. Origins the design loads fonts, stylesheets and images from (https://fonts.googleapis.com, https://*.cdn.example.com). The organization allows them in Settings → Security; kaloko design lint warns about one it does not allow. Scripts never load from them." },
|
|
229
|
-
"
|
|
229
|
+
"default_token_mode": { "type": "string", "description": "kind: design. Token mode (e.g. light, dark) steps are rendered in and the checks use; default: the token set's first mode. tokens_mode is its older name." },
|
|
230
|
+
"tokens_mode": { "type": "string", "description": "kind: design. The older name of default_token_mode; still read." },
|
|
230
231
|
"token_modes": { "oneOf": [{ "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{0,39}$" } }, { "const": false }], "description": "kind: design. Token modes of the token set to render every step in, one capture per mode (keys <viewport>.mode-<name>); tokens_mode is the default and has the plain key. Not set: every mode of the set when it has two or more, except a set of only light and dark (left to color_schemes). false: only tokens_mode." },
|
|
231
232
|
"html_view": { "type": "boolean", "default": false, "description": "Experimental (#42): keep a static HTML view of every capture (assets rehosted, scripts removed, secrets scrubbed). Refused on production unless the environment is readonly." },
|
|
232
233
|
"base_url": {
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://qawalk.com/schemas/evidence.v1.json",
|
|
4
|
+
"title": "Kaloko evidence (qawalk.evidence.v1)",
|
|
5
|
+
"description": "What a downstream generator reads from Kaloko to write its own documentation: the evidence of a run (kind run), of a release (kind release), the trace matrix on its own (kind trace) and the MANIFEST.json of an evidence package (kind package). The contract is additive: new fields may appear in v1, existing fields keep their meaning and type; a breaking change makes qawalk.evidence.v2. Kaloko never formats output for a particular QMS. Produced by GET /api/v1/orgs/<org>/runs/<id>/evidence, …/evidence.zip, …/trace.json, GET /api/v1/orgs/<org>/evidence?product=&version=, MCP get_evidence and kaloko evidence.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schema", "kind"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema": { "const": "qawalk.evidence.v1" },
|
|
10
|
+
"kind": { "enum": ["run", "release", "trace", "package"] }
|
|
11
|
+
},
|
|
12
|
+
"allOf": [
|
|
13
|
+
{ "if": { "properties": { "kind": { "const": "run" } } }, "then": { "$ref": "#/$defs/run" } },
|
|
14
|
+
{ "if": { "properties": { "kind": { "const": "release" } } }, "then": { "$ref": "#/$defs/release" } },
|
|
15
|
+
{ "if": { "properties": { "kind": { "const": "trace" } } }, "then": { "$ref": "#/$defs/trace" } },
|
|
16
|
+
{ "if": { "properties": { "kind": { "const": "package" } } }, "then": { "$ref": "#/$defs/package" } }
|
|
17
|
+
],
|
|
18
|
+
"$defs": {
|
|
19
|
+
"time": { "type": ["string", "null"], "description": "ISO 8601 time in UTC (…Z), from the service's clock." },
|
|
20
|
+
"sha256": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$", "description": "SHA-256, lowercase hex." },
|
|
21
|
+
"refs": { "type": "array", "items": { "type": "string" }, "description": "Requirement references as written in the scenario (refs:), free text, never interpreted." },
|
|
22
|
+
"run": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"required": ["generated_at", "acceptance", "signing", "record", "run", "scenario", "steps", "signatures", "trace"],
|
|
25
|
+
"properties": {
|
|
26
|
+
"generated_at": { "$ref": "#/$defs/time", "description": "When this document was made. It is not signed itself; record.sha256 names the signed record it was made from." },
|
|
27
|
+
"issuer": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"properties": {
|
|
30
|
+
"service": { "type": ["string", "null"], "description": "The Kaloko service that holds the run, e.g. https://kaloko.app." },
|
|
31
|
+
"commit": { "type": ["string", "null"], "description": "The service's deployed version (git commit), when known." },
|
|
32
|
+
"public_keys": { "type": ["string", "null"], "description": "URL of the public keys the record and the package manifest verify against (/.well-known/kaloko-signoff.json)." }
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"org": { "type": ["object", "null"], "properties": { "slug": { "type": "string" }, "name": { "type": ["string", "null"] } } },
|
|
36
|
+
"acceptance": { "enum": ["none", "accepted", "returned"], "description": "The run's acceptance in Kaloko: accepted, returned, or none (nobody decided the run, or the decision was reset). A generator writes from this, never from the presence of other fields." },
|
|
37
|
+
"signing": { "enum": ["in_kaloko", "none"], "description": "in_kaloko: at least one electronic signature made in Kaloko stands (see signatures). none: no signature in Kaloko; if the approval is signed, it is signed in another system (the client's eQMS) and that system holds it." },
|
|
38
|
+
"record": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"description": "The signed record this evidence was derived from (record/kaloko-signoff.json in the package).",
|
|
41
|
+
"properties": {
|
|
42
|
+
"schema": { "type": ["string", "null"], "description": "kaloko.signoff.v1." },
|
|
43
|
+
"kind": { "enum": ["acceptance", "execution"], "description": "acceptance: the stored record of an accepted run (byte-identical on every download while its verdict and signatures stay). execution: a run that is not accepted; signed when made, not stored." },
|
|
44
|
+
"sha256": { "$ref": "#/$defs/sha256", "description": "SHA-256 of the record's canonical JSON without its signature: what kaloko signoff --verify prints as the record hash." },
|
|
45
|
+
"signed": { "type": "boolean", "description": "The record carries the service's Ed25519 signature." },
|
|
46
|
+
"kid": { "type": ["string", "null"], "description": "Id of the signing key." },
|
|
47
|
+
"issued_at": { "$ref": "#/$defs/time" },
|
|
48
|
+
"exported_by": { "type": ["string", "null"], "description": "Who downloaded the record first (e-mail)." }
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"run": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"id": { "type": "string" },
|
|
55
|
+
"url": { "type": ["string", "null"], "description": "The run on the canvas." },
|
|
56
|
+
"project": { "type": ["string", "null"] },
|
|
57
|
+
"started_at": { "$ref": "#/$defs/time", "description": "When the walk started (the walking machine's clock)." },
|
|
58
|
+
"finished_at": { "$ref": "#/$defs/time", "description": "When the manifest was built (the walking machine's clock)." },
|
|
59
|
+
"version": { "type": ["string", "null"], "description": "Design version, for runs of design environments." },
|
|
60
|
+
"app_version": { "type": ["string", "null"], "description": "Version of the application under test, when the run names one." }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"scenario": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"properties": {
|
|
66
|
+
"id": { "type": "string" },
|
|
67
|
+
"title": { "type": ["string", "null"] },
|
|
68
|
+
"version": { "type": ["integer", "string", "null"], "description": "The scenario's own version: field, when set." },
|
|
69
|
+
"file": { "type": ["string", "null"], "description": "Path of the scenario file in the repository." },
|
|
70
|
+
"sha256": { "$ref": "#/$defs/sha256", "description": "SHA-256 of the scenario file as walked (CLI 0.15+; null before)." },
|
|
71
|
+
"refs": { "$ref": "#/$defs/refs" }
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"environment": { "type": ["object", "null"], "description": "{ name, url }: the environment and its base URL." },
|
|
75
|
+
"git": { "type": ["object", "null"], "description": "{ commit, branch, repo } of the code the run walked, when known." },
|
|
76
|
+
"tools": {
|
|
77
|
+
"type": ["object", "null"],
|
|
78
|
+
"description": "What walked and evaluated the run.",
|
|
79
|
+
"properties": {
|
|
80
|
+
"cli": { "type": ["object", "null"], "description": "{ name, version } of the Kaloko CLI (null version: walked before 0.15)." },
|
|
81
|
+
"node": { "type": ["string", "null"] },
|
|
82
|
+
"os": { "type": ["string", "null"] },
|
|
83
|
+
"browsers": { "type": "array", "items": { "type": "string" }, "description": "Browser engines and versions seen in the captures, e.g. \"chromium 131.0.6778.33\"." },
|
|
84
|
+
"executor": { "type": ["object", "null"], "description": "{ kind: cli | agent, name }." },
|
|
85
|
+
"service": { "type": ["object", "null"], "description": "{ url, commit } of the service that signed the record." }
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"manifest": { "type": ["object", "null"], "description": "{ path: run.json, sha256, bytes }: the run manifest as stored. Every signature is bound to this hash." },
|
|
89
|
+
"verdict": { "type": ["object", "null"], "description": "{ verdict: pending | accepted | returned, by, via: session | token | agent, at, note, country, counts_as_person }. via session is a person in the app; token and agent are never a person's decision." },
|
|
90
|
+
"approvals": { "type": ["object", "null"], "description": "{ required: [e-mail], people: [{ email, at }], tokens_and_agents: [{ email, at, via, counts_as_person: false }] }." },
|
|
91
|
+
"summary": { "type": ["object", "null"] },
|
|
92
|
+
"ai": { "type": ["object", "null"], "description": "{ advisory: true, models: [model id], statement }: AI verdicts are advisory; the decisions that count are a person's." },
|
|
93
|
+
"advisory": { "type": ["object", "null"], "description": "Results the run carries besides its acceptance criteria (e.g. a health section), copied as they are. They never change acceptance." },
|
|
94
|
+
"steps": {
|
|
95
|
+
"type": "array",
|
|
96
|
+
"items": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"properties": {
|
|
99
|
+
"id": { "type": "string" },
|
|
100
|
+
"kind": { "type": "string" },
|
|
101
|
+
"title": { "type": ["string", "null"] },
|
|
102
|
+
"refs": { "$ref": "#/$defs/refs" },
|
|
103
|
+
"status": { "enum": ["pass", "partial", "fail", "skip"] },
|
|
104
|
+
"decision": { "type": ["object", "null"], "description": "The step's current decision: { id, state: approved | returned, by, at, via, agent?, counts_as_person, note?, attachments?: [{ id, name, type, bytes, sha256, by, at, path: decisions/<step>/<file> in the evidence package }], pin?, shape? }." },
|
|
105
|
+
"decisions": { "type": "array", "description": "Every decision on the step, oldest first, shaped like decision; superseded ones too (resolved_at, deleted: true without content)." },
|
|
106
|
+
"carried": { "type": ["object", "null"], "description": "An approval carried over from an earlier accepted run: { from_run, compared_run, kind, approved_by, approved_at, approved_via }." },
|
|
107
|
+
"criteria": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"properties": {
|
|
112
|
+
"id": { "type": "string" },
|
|
113
|
+
"text": { "type": ["string", "null"], "description": "The criterion as walked (from the scenario at the time of the run)." },
|
|
114
|
+
"type": { "type": ["string", "null"], "description": "deterministic, semantic or manual." },
|
|
115
|
+
"pack": { "type": "string", "description": "The pack the criterion came from, when it did." },
|
|
116
|
+
"refs": { "$ref": "#/$defs/refs" },
|
|
117
|
+
"verdict": { "type": "string", "description": "pass, fail, needs_review, not_evaluated or not_reached; the worst over locales and viewports after people's verdicts." },
|
|
118
|
+
"assessed_by": { "enum": ["person", "ai", "deterministic", "none"] },
|
|
119
|
+
"models": { "type": "array", "items": { "type": "string" }, "description": "AI models that assessed it." },
|
|
120
|
+
"advisory": { "type": "boolean", "description": "true: the result is an AI's and no person decided this criterion." },
|
|
121
|
+
"results": {
|
|
122
|
+
"type": "array",
|
|
123
|
+
"items": {
|
|
124
|
+
"type": "object",
|
|
125
|
+
"properties": {
|
|
126
|
+
"locale": { "type": "string" },
|
|
127
|
+
"viewport": { "type": "string" },
|
|
128
|
+
"verdict": { "type": "string" },
|
|
129
|
+
"score": { "type": "number", "description": "The AI's probability that the criterion holds (0–1)." },
|
|
130
|
+
"assessed_by": { "enum": ["person", "ai", "deterministic", "none"] },
|
|
131
|
+
"assessor": { "type": ["string", "null"], "description": "The person's e-mail, or the AI model id." },
|
|
132
|
+
"advisory": { "type": "boolean" }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"reviewer": { "type": "array", "description": "Criterion verdicts set by people: { email, verdict, note, locale, at }." }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"captures": {
|
|
141
|
+
"type": "array",
|
|
142
|
+
"items": { "type": "object", "properties": { "locale": { "type": "string" }, "viewport": { "type": "string" }, "path": { "type": ["string", "null"], "description": "Path in the run; the package stores it under captures/<path>." }, "sha256": { "$ref": "#/$defs/sha256" } } }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"signatures": {
|
|
148
|
+
"type": "array",
|
|
149
|
+
"description": "Electronic signatures made in Kaloko, oldest first, withdrawn ones included. Empty unless the organization signs in Kaloko.",
|
|
150
|
+
"items": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"properties": {
|
|
153
|
+
"id": { "type": "string" },
|
|
154
|
+
"scope": { "enum": ["run", "step"] },
|
|
155
|
+
"step": { "type": ["string", "null"] },
|
|
156
|
+
"review": { "type": ["string", "null"], "description": "The step approval it signs (comment id)." },
|
|
157
|
+
"decision": { "type": "string", "description": "accepted (run) or approved (step)." },
|
|
158
|
+
"meaning": { "type": "string", "description": "The meaning the signer chose from the organization's list, as the label they saw." },
|
|
159
|
+
"meaning_id": { "type": ["string", "null"], "description": "subject_v 2: the meaning's id (reviewed, approved, verified, or the organization's own)." },
|
|
160
|
+
"lang": { "type": ["string", "null"], "description": "subject_v 2: the language the meaning's label was shown in (en, cs)." },
|
|
161
|
+
"subject_v": { "type": "integer", "description": "2 for signatures made since 7 Oct 2026; absent (1) before." },
|
|
162
|
+
"decision_sha256": { "type": ["string", "null"], "description": "subject_v 2: SHA-256 of the canonical decision { note, attachments [{ name, bytes, sha256 }], pin, shape } (a run: its note)." },
|
|
163
|
+
"name": { "type": "string", "description": "Printed name of the signer." },
|
|
164
|
+
"email": { "type": "string" },
|
|
165
|
+
"signed_at": { "$ref": "#/$defs/time" },
|
|
166
|
+
"time_zone": { "type": "string", "description": "The signer's IANA time zone." },
|
|
167
|
+
"local_time": { "type": "string", "description": "The signing time in the signer's zone with its UTC offset." },
|
|
168
|
+
"auth": { "type": "object", "description": "{ session: how the session signed in, second_step_at: when the second step was confirmed, second_step_by: kaloko | idp }." },
|
|
169
|
+
"verdict_at": { "$ref": "#/$defs/time" },
|
|
170
|
+
"manifest_sha256": { "$ref": "#/$defs/sha256" },
|
|
171
|
+
"subject_sha256": { "$ref": "#/$defs/sha256", "description": "SHA-256 of the canonical JSON { v: 1, run, step, decision, meaning, email, name, signed_at, manifest_sha256 } (subject_v 2 adds meaning_id, lang and decision_sha256): what was signed. kaloko signoff --verify recomputes it." },
|
|
172
|
+
"withdrawn": { "type": ["object", "null"], "description": "{ at, by, reason } once the decision changed; the signature is never rewritten otherwise." }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"decision_changes": { "type": "array", "description": "Withdrawn signatures: { at, by, reason, signature, scope, step, signed_by, meaning }." },
|
|
177
|
+
"audit": {
|
|
178
|
+
"type": "array",
|
|
179
|
+
"description": "The audit trail of the run, oldest first: rows of the audit log about the run (source audit_log) and its decisions from comments and criterion verdicts (source decisions).",
|
|
180
|
+
"items": { "type": "object", "properties": { "at": { "$ref": "#/$defs/time" }, "actor": { "type": ["string", "null"] }, "action": { "type": ["string", "null"] }, "target": { "type": ["string", "null"] }, "via": { "type": ["string", "null"] }, "agent": { "type": ["string", "null"] }, "country": { "type": ["string", "null"] }, "source": { "enum": ["audit_log", "decisions"] }, "detail": {} } }
|
|
181
|
+
},
|
|
182
|
+
"trace": { "type": "array", "items": { "$ref": "#/$defs/traceRow" } }
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"traceRow": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"description": "One row of the trace matrix: a requirement, a criterion, a step in one locale and viewport, its screenshot, the result and the decisions. A criterion's requirements are its own refs, its step's and its scenario's (requirement_level); a criterion without any gets one row with requirement null. The CSV has these columns in this order.",
|
|
188
|
+
"properties": {
|
|
189
|
+
"requirement": { "type": ["string", "null"] },
|
|
190
|
+
"requirement_level": { "enum": ["criterion", "step", "scenario", null] },
|
|
191
|
+
"run_id": { "type": ["string", "null"] },
|
|
192
|
+
"scenario_id": { "type": ["string", "null"] },
|
|
193
|
+
"scenario_version": { "type": ["integer", "string", "null"] },
|
|
194
|
+
"step_id": { "type": "string" },
|
|
195
|
+
"step_title": { "type": ["string", "null"] },
|
|
196
|
+
"criterion_id": { "type": "string" },
|
|
197
|
+
"criterion_text": { "type": ["string", "null"] },
|
|
198
|
+
"criterion_type": { "type": ["string", "null"] },
|
|
199
|
+
"locale": { "type": ["string", "null"] },
|
|
200
|
+
"viewport": { "type": ["string", "null"] },
|
|
201
|
+
"evidence_file": { "type": ["string", "null"] },
|
|
202
|
+
"evidence_sha256": { "$ref": "#/$defs/sha256" },
|
|
203
|
+
"result": { "type": ["string", "null"] },
|
|
204
|
+
"assessed_by": { "type": ["string", "null"] },
|
|
205
|
+
"assessor": { "type": ["string", "null"] },
|
|
206
|
+
"advisory": { "type": "boolean" },
|
|
207
|
+
"step_decision": { "type": ["string", "null"] },
|
|
208
|
+
"step_decided_by": { "type": ["string", "null"] },
|
|
209
|
+
"step_decided_at": { "$ref": "#/$defs/time" },
|
|
210
|
+
"step_decided_via": { "type": ["string", "null"] },
|
|
211
|
+
"step_signature_meaning": { "type": ["string", "null"] },
|
|
212
|
+
"step_signer_name": { "type": ["string", "null"] },
|
|
213
|
+
"step_signed_at": { "$ref": "#/$defs/time" },
|
|
214
|
+
"step_signer_time_zone": { "type": ["string", "null"] },
|
|
215
|
+
"step_comment": { "type": ["string", "null"] },
|
|
216
|
+
"run_verdict": { "type": ["string", "null"] },
|
|
217
|
+
"run_decided_by": { "type": ["string", "null"] },
|
|
218
|
+
"run_decided_at": { "$ref": "#/$defs/time" },
|
|
219
|
+
"run_decided_via": { "type": ["string", "null"] },
|
|
220
|
+
"run_signature_meaning": { "type": ["string", "null"] },
|
|
221
|
+
"run_signer_name": { "type": ["string", "null"] },
|
|
222
|
+
"run_signed_at": { "$ref": "#/$defs/time" },
|
|
223
|
+
"run_signer_time_zone": { "type": ["string", "null"] }
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
"release": {
|
|
227
|
+
"type": "object",
|
|
228
|
+
"required": ["release", "runs", "trace"],
|
|
229
|
+
"properties": {
|
|
230
|
+
"generated_at": { "$ref": "#/$defs/time" },
|
|
231
|
+
"release": { "type": "object", "description": "{ product, version, released_on, tag, commit, runs: [run id] }." },
|
|
232
|
+
"runs": { "type": "array", "items": { "$ref": "#/$defs/run" }, "description": "The evidence of each run of the release the caller can read." },
|
|
233
|
+
"missing": { "type": "array", "items": { "type": "object", "properties": { "run": { "type": "string" }, "reason": { "type": "string" } } }, "description": "Runs of the release without evidence here, with the reason." },
|
|
234
|
+
"trace": { "type": "array", "items": { "$ref": "#/$defs/traceRow" } }
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"trace": {
|
|
238
|
+
"type": "object",
|
|
239
|
+
"required": ["rows"],
|
|
240
|
+
"properties": { "run": { "type": "string" }, "record_sha256": { "$ref": "#/$defs/sha256" }, "rows": { "type": "array", "items": { "$ref": "#/$defs/traceRow" } } }
|
|
241
|
+
},
|
|
242
|
+
"package": {
|
|
243
|
+
"type": "object",
|
|
244
|
+
"required": ["files", "signature"],
|
|
245
|
+
"description": "MANIFEST.json of an evidence package, signed like a record (Ed25519 over its canonical JSON without signature).",
|
|
246
|
+
"properties": {
|
|
247
|
+
"created_at": { "$ref": "#/$defs/time" },
|
|
248
|
+
"issuer": { "type": "object", "description": "{ service, kid, public_keys }." },
|
|
249
|
+
"run": { "type": "string" },
|
|
250
|
+
"record_sha256": { "$ref": "#/$defs/sha256" },
|
|
251
|
+
"files": { "type": "array", "items": { "type": "object", "properties": { "path": { "type": "string" }, "sha256": { "$ref": "#/$defs/sha256" }, "bytes": { "type": "integer" } } } },
|
|
252
|
+
"missing": { "type": "array", "items": { "type": "string" }, "description": "Screenshots the record names that could not be read when the package was made." },
|
|
253
|
+
"signature": { "type": "object", "description": "{ alg: Ed25519, kid, value, canonical: kaloko-c14n-v1 }." }
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
package/schemas/run.v1.json
CHANGED
|
@@ -50,6 +50,15 @@
|
|
|
50
50
|
"file": {
|
|
51
51
|
"type": "string"
|
|
52
52
|
},
|
|
53
|
+
"sha256": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "SHA-256 of the scenario file as it was walked (kaloko 0.15+)."
|
|
56
|
+
},
|
|
57
|
+
"refs": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"items": { "type": "string" },
|
|
60
|
+
"description": "Requirement references of the scenario (scenario refs:)."
|
|
61
|
+
},
|
|
53
62
|
"source": {
|
|
54
63
|
"type": [
|
|
55
64
|
"string",
|
|
@@ -132,6 +141,16 @@
|
|
|
132
141
|
"null"
|
|
133
142
|
]
|
|
134
143
|
},
|
|
144
|
+
"tools": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"description": "What walked the run (kaloko 0.15+): cli {name, version}, node (the Node.js version), os (platform and architecture), browsers (engine versions seen in the captures).",
|
|
147
|
+
"properties": {
|
|
148
|
+
"cli": { "type": "object" },
|
|
149
|
+
"node": { "type": ["string", "null"] },
|
|
150
|
+
"os": { "type": ["string", "null"] },
|
|
151
|
+
"browsers": { "type": "array", "items": { "type": "string" } }
|
|
152
|
+
}
|
|
153
|
+
},
|
|
135
154
|
"started_at": {
|
|
136
155
|
"type": "string"
|
|
137
156
|
},
|
|
@@ -227,6 +246,17 @@
|
|
|
227
246
|
},
|
|
228
247
|
"criteria": {
|
|
229
248
|
"type": "object"
|
|
249
|
+
},
|
|
250
|
+
"health": {
|
|
251
|
+
"type": "object",
|
|
252
|
+
"description": "Health counts (advisory, CS Kondice): checks evaluated and findings by severity (error, warning; info = the evaluator was unsure), also per pack. Never part of pass, partial or fail.",
|
|
253
|
+
"properties": {
|
|
254
|
+
"checks": { "type": "integer" },
|
|
255
|
+
"error": { "type": "integer" },
|
|
256
|
+
"warning": { "type": "integer" },
|
|
257
|
+
"info": { "type": "integer" },
|
|
258
|
+
"packs": { "type": "object" }
|
|
259
|
+
}
|
|
230
260
|
}
|
|
231
261
|
}
|
|
232
262
|
},
|
|
@@ -417,6 +447,11 @@
|
|
|
417
447
|
"purpose": {
|
|
418
448
|
"type": "string"
|
|
419
449
|
},
|
|
450
|
+
"refs": {
|
|
451
|
+
"type": "array",
|
|
452
|
+
"items": { "type": "string" },
|
|
453
|
+
"description": "Requirement references of the step (refs: in the scenario)."
|
|
454
|
+
},
|
|
420
455
|
"col": {
|
|
421
456
|
"type": "integer"
|
|
422
457
|
},
|
|
@@ -535,6 +570,11 @@
|
|
|
535
570
|
"verdict": {
|
|
536
571
|
"$ref": "#/$defs/verdict"
|
|
537
572
|
},
|
|
573
|
+
"refs": {
|
|
574
|
+
"type": "array",
|
|
575
|
+
"items": { "type": "string" },
|
|
576
|
+
"description": "Requirement references of the criterion (refs: in the scenario)."
|
|
577
|
+
},
|
|
538
578
|
"by_locale": {
|
|
539
579
|
"type": "object"
|
|
540
580
|
},
|
|
@@ -559,7 +599,33 @@
|
|
|
559
599
|
},
|
|
560
600
|
"check": {
|
|
561
601
|
"type": "object"
|
|
562
|
-
}
|
|
602
|
+
},
|
|
603
|
+
"pack": {
|
|
604
|
+
"type": ["string", "null"],
|
|
605
|
+
"description": "The check pack the criterion comes from. In criteria a pack criterion counts for acceptance only with acceptance: true; runs stored before health was split off have pack criteria here without it (readers show them as health; their stored verdicts stay)."
|
|
606
|
+
},
|
|
607
|
+
"acceptance": { "type": "boolean" },
|
|
608
|
+
"from": { "type": "string", "description": "The health check an adopted criterion came from (e.g. HC302)." }
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
"health": {
|
|
613
|
+
"type": "array",
|
|
614
|
+
"description": "Health checks (CS Kondice): criteria of check packs outside acceptance, shaped like criteria plus level (error or warning when the check fails). Advisory: they never decide the step status or the run verdict. Absent when the step has none.",
|
|
615
|
+
"items": {
|
|
616
|
+
"type": "object",
|
|
617
|
+
"required": ["id", "text", "verdict"],
|
|
618
|
+
"properties": {
|
|
619
|
+
"id": { "type": "string", "description": "Health check id, HC<n> (HC302). Runs written before 7 Oct 2026 store AC<n>; readers map it to HC<n>." },
|
|
620
|
+
"text": { "type": "string" },
|
|
621
|
+
"pack": { "type": ["string", "null"] },
|
|
622
|
+
"level": { "enum": ["error", "warning"] },
|
|
623
|
+
"verdict": { "$ref": "#/$defs/verdict" },
|
|
624
|
+
"by_locale": { "type": "object" },
|
|
625
|
+
"counts": { "type": "object", "description": "Stack steps: pages per verdict." },
|
|
626
|
+
"evidence": { "type": ["string", "null"] },
|
|
627
|
+
"check": { "type": "object" },
|
|
628
|
+
"help": { "type": "object" }
|
|
563
629
|
}
|
|
564
630
|
}
|
|
565
631
|
},
|
package/schemas/scenario.v1.json
CHANGED
|
@@ -89,12 +89,23 @@
|
|
|
89
89
|
"enum": ["landing", "work", "list", "settings", "form", "doc"],
|
|
90
90
|
"description": "Default page type of every step (a step may set its own). landing: a public or marketing page; work: an app screen where people work (overview, canvas, inbox); list: a list or table of items; settings: settings or billing; form: a form to fill in; doc: documentation or long text. The usability pack picks its questions by type. Not set: landing for steps with the seo pack or scenarios allowed on production, work otherwise."
|
|
91
91
|
},
|
|
92
|
+
"health": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"additionalProperties": false,
|
|
95
|
+
"description": "Health (CS Kondice): the checks of packs are advisory, shown apart from acceptance and never part of a verdict. acceptance lists the packs whose checks still count for acceptance in this scenario, as they did before health was split off (the design pack always does). To make one check count, adopt it: kaloko health adopt <step>:<check> (e.g. home:HC103) adds the criterion AC103 with from: HC103.",
|
|
96
|
+
"properties": {
|
|
97
|
+
"acceptance": { "type": "array", "uniqueItems": true, "items": { "enum": ["seo", "usability", "a11y", "perf", "console", "errors", "app", "design"] } }
|
|
98
|
+
}
|
|
99
|
+
},
|
|
92
100
|
"tags": {
|
|
93
101
|
"type": "array",
|
|
94
102
|
"items": {
|
|
95
103
|
"type": "string"
|
|
96
104
|
}
|
|
97
105
|
},
|
|
106
|
+
"refs": {
|
|
107
|
+
"$ref": "#/$defs/refs"
|
|
108
|
+
},
|
|
98
109
|
"nodes": {
|
|
99
110
|
"type": "array",
|
|
100
111
|
"minItems": 1,
|
|
@@ -193,6 +204,13 @@
|
|
|
193
204
|
}
|
|
194
205
|
},
|
|
195
206
|
"$defs": {
|
|
207
|
+
"refs": {
|
|
208
|
+
"description": "Requirement references this part verifies, as your QMS or tracker writes them (URS-12, FS-3.4, JIRA-1234). Free text; Kaloko carries them into the run, the acceptance record and the trace matrix (qawalk.evidence.v1) and never interprets them.",
|
|
209
|
+
"type": "array",
|
|
210
|
+
"maxItems": 50,
|
|
211
|
+
"uniqueItems": true,
|
|
212
|
+
"items": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^\\S(.*\\S)?$" }
|
|
213
|
+
},
|
|
196
214
|
"record": {
|
|
197
215
|
"description": "Recordings of walked steps (opt-in): true or step records each step from the previous screen to its capture; flow records the whole walk per locale with a chapter per step; failed keeps only steps that fail; false or off turns it off. Uploaded on Business and Enterprise.",
|
|
198
216
|
"oneOf": [
|
|
@@ -277,6 +295,9 @@
|
|
|
277
295
|
"purpose": {
|
|
278
296
|
"type": "string"
|
|
279
297
|
},
|
|
298
|
+
"refs": {
|
|
299
|
+
"$ref": "#/$defs/refs"
|
|
300
|
+
},
|
|
280
301
|
"lane": {
|
|
281
302
|
"type": "integer",
|
|
282
303
|
"minimum": 0
|
|
@@ -341,7 +362,7 @@
|
|
|
341
362
|
"design"
|
|
342
363
|
]
|
|
343
364
|
},
|
|
344
|
-
"description": "Check packs whose
|
|
365
|
+
"description": "Check packs whose checks are added to this node. Health checks (advisory): HC1xx seo, HC2xx usability, HC3xx a11y, HC4xx perf, HC5xx console, HC6xx errors, HC7xx app. AC8xx design: checks against the design reference, always acceptance. A pack listed in health.acceptance adds its checks as acceptance criteria with the same number (HC302 → AC302)."
|
|
345
366
|
},
|
|
346
367
|
"capture": {
|
|
347
368
|
"$ref": "#/$defs/capture"
|
|
@@ -532,6 +553,9 @@
|
|
|
532
553
|
"type": "string",
|
|
533
554
|
"description": "CSS selector to outline in the screenshot."
|
|
534
555
|
},
|
|
556
|
+
"refs": {
|
|
557
|
+
"$ref": "#/$defs/refs"
|
|
558
|
+
},
|
|
535
559
|
"check": {
|
|
536
560
|
"oneOf": [
|
|
537
561
|
{
|
|
@@ -549,6 +573,15 @@
|
|
|
549
573
|
"type": "string",
|
|
550
574
|
"description": "Set by the CLI on criteria that came from a pack."
|
|
551
575
|
},
|
|
576
|
+
"from": {
|
|
577
|
+
"type": "string",
|
|
578
|
+
"pattern": "^(HC|AC)[0-9]+$",
|
|
579
|
+
"description": "The health check this criterion was adopted from (kaloko health adopt), e.g. HC302. The step's pack then leaves that check out of its health, so it is not shown twice. AC302 (written before the HC ids) reads as HC302."
|
|
580
|
+
},
|
|
581
|
+
"acceptance": {
|
|
582
|
+
"type": "boolean",
|
|
583
|
+
"description": "Set by the CLI on criteria of a pack that counts for acceptance (design, or health.acceptance). Without it a pack criterion is a health check: advisory, never part of a verdict."
|
|
584
|
+
},
|
|
552
585
|
"environments": {
|
|
553
586
|
"type": "array",
|
|
554
587
|
"minItems": 1,
|
package/skills/kaloko/SKILL.md
CHANGED
|
@@ -22,8 +22,13 @@ description: >
|
|
|
22
22
|
kaloko changelog draft, kaloko release) or a guide should show a step or
|
|
23
23
|
be written, translated or checked (kaloko docs check), when screenshots,
|
|
24
24
|
HTML or recordings must hide personal data (capture masks, pii: redact or
|
|
25
|
-
pseudonymize, kaloko share stopping on unmasked data),
|
|
26
|
-
Clef triage findings (experimental) to read, mention or answer
|
|
25
|
+
pseudonymize, kaloko share stopping on unmasked data), when a run has
|
|
26
|
+
Clef triage findings (experimental) to read, mention or answer, when
|
|
27
|
+
a run's health (the advisory checks of packs: SEO, accessibility,
|
|
28
|
+
performance, console) should be checked, fixed or adopted into acceptance,
|
|
29
|
+
and when a team's own repository turns runs into regulated documentation
|
|
30
|
+
(requirement refs, kaloko evidence, the evidence package, the evidence.ready
|
|
31
|
+
webhook).
|
|
27
32
|
---
|
|
28
33
|
|
|
29
34
|
# Kaloko
|
|
@@ -39,6 +44,9 @@ the canvas, storage and collaboration are the service.
|
|
|
39
44
|
- The captures are evaluated (`kaloko walk` ends with the verdicts; after
|
|
40
45
|
`kaloko capture` run `kaloko evaluate`) and `kaloko build` ran; you report the summary line,
|
|
41
46
|
failing criteria with evidence, and the preview path (or shared URL).
|
|
47
|
+
- Health was checked before you hand over (`kaloko health`, MCP `get_health`):
|
|
48
|
+
you fixed what your change can fix, and you report the remaining counts and
|
|
49
|
+
what is new since the previous run, apart from the verdicts.
|
|
42
50
|
- When the run was shared, its URL and the summary are in the issue or PR
|
|
43
51
|
the work belongs to, the person got the review-mode link with what waits
|
|
44
52
|
for them (`kaloko share` prints it; `kaloko review` repeats it), and you
|
|
@@ -83,11 +91,14 @@ Draft and edit the Unreleased section of the changelog (`kaloko changelog draft
|
|
|
83
91
|
config on Kaloko (`kaloko products sync`: it records no release) and list them
|
|
84
92
|
(`kaloko products list`). Write, translate and fix
|
|
85
93
|
guides in the docs folder, run `kaloko docs check`, and export them for a docs
|
|
86
|
-
site (`kaloko export --format …`) into a local folder.
|
|
94
|
+
site (`kaloko export docs --format …`) into a local folder.
|
|
87
95
|
|
|
88
96
|
## Ask first
|
|
89
97
|
|
|
90
|
-
Changing acceptance criteria or scope
|
|
98
|
+
Changing acceptance criteria or scope (adopting a health check into
|
|
99
|
+
acceptance with `kaloko health adopt` is such a change; pulling checks a
|
|
100
|
+
person already adopted with `kaloko health pull` is not), removing a pack or
|
|
101
|
+
keeping one in acceptance (`health.acceptance`), any production run, writing or
|
|
91
102
|
replacing a CI workflow (`kaloko ci github|gitlab`), uploading with
|
|
92
103
|
`kaloko share` (on a design environment: publishing a version), setting a
|
|
93
104
|
design reference or baseline, merging a design branch, keeping your version of
|
|
@@ -102,7 +113,8 @@ anything the environment profile blocks. Never trash an accepted run, a
|
|
|
102
113
|
baseline, a run with review comments, or a run linked from an open PR or issue
|
|
103
114
|
comment. Never approve a
|
|
104
115
|
step or accept a run on a person's behalf, and never hand out a signed
|
|
105
|
-
acceptance record (`kaloko signoff`) for a run a person has not accepted
|
|
116
|
+
acceptance record (`kaloko signoff`) for a run a person has not accepted, never present an AI verdict as a person's
|
|
117
|
+
decision in generated documents, and never change the signature policy; report what waits for them
|
|
106
118
|
(`kaloko review`, MCP `get_review_queue`) instead. Ask the person
|
|
107
119
|
for secret values (passwords, tokens, gate credentials) and for sign-ins only
|
|
108
120
|
they can do; never write secrets into the config, a scenario or a script. When
|
|
@@ -131,6 +143,9 @@ only when a person says that value may be uploaded.
|
|
|
131
143
|
(`--heal`): [reference/execution.md](reference/execution.md)
|
|
132
144
|
- Evaluation, JEV thresholds, the vision evaluator and its reasons, reading
|
|
133
145
|
results: [reference/evaluation.md](reference/evaluation.md)
|
|
146
|
+
- Health (CS Kondice): the advisory checks of packs, `kaloko health`,
|
|
147
|
+
severities, fixing before review, adopting a check into acceptance, alerts:
|
|
148
|
+
[reference/evaluation.md#health](reference/evaluation.md#health)
|
|
134
149
|
- Clef triage findings (experimental): what they are, how to report them apart
|
|
135
150
|
from the verdicts, `get_findings` and `answer_finding`:
|
|
136
151
|
[reference/evaluation.md#triage-findings-experimental](reference/evaluation.md#triage-findings-experimental)
|
|
@@ -154,6 +169,10 @@ only when a person says that value may be uploaded.
|
|
|
154
169
|
[reference/collaboration.md](reference/collaboration.md)
|
|
155
170
|
- Reading runs, feedback and the inbox over MCP instead of the CLI:
|
|
156
171
|
[reference/mcp.md](reference/mcp.md)
|
|
172
|
+
- Evidence for regulated work (GxP): requirement `refs:`, `kaloko evidence`,
|
|
173
|
+
the evidence package and its check, the `evidence.ready` webhook, feeding a
|
|
174
|
+
team's own document templates, signatures and what an agent must never do:
|
|
175
|
+
[reference/evidence.md](reference/evidence.md)
|
|
157
176
|
- Filing a returned step or a failing criterion in Jira or Linear, issue keys in
|
|
158
177
|
branches, channels per project, and hosted runs of read-only scenarios on a
|
|
159
178
|
schedule (`kaloko issue`, `kaloko schedule`):
|