verikun 0.7.0 → 0.8.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 CHANGED
@@ -232,6 +232,11 @@ a hard iteration cap and stop early if the screen stops changing.
232
232
  - An `ai` run records like any other flow, so it produces the same JUnit + HTML report —
233
233
  with the cost line and any **suggested test improvements** (workarounds the model
234
234
  applied, which you can fold back into the prose to stabilize the test and cut tokens).
235
+ - **Review screenshots are inserted automatically.** The compiler adds `screenshot` steps
236
+ around transitions and inside loops, so the report carries a before/after visual trail
237
+ for post-run review. They are dumped for humans, never read back by the model (no token
238
+ cost on replay), and never gate the test — a capture that hiccups is logged and skipped,
239
+ not a failure.
235
240
 
236
241
  ## Suites — run a directory of tests
237
242
 
@@ -424,6 +429,13 @@ safely resample (palette, 16-bit, interlaced) are written through untouched, so
424
429
  screenshot is never corrupted — only sometimes left full-size (noted on stderr).
425
430
  Failure-evidence captures in test-run reports stay full-resolution for debugging.
426
431
 
432
+ **Read-back vs evidence.** The downscaling above matters when an agent *reads a
433
+ screenshot back into its context* to decide the next action — that is the token cost to
434
+ manage. A screenshot taken purely as **report evidence and never read back** costs nothing
435
+ at runtime, so driving a flow to a report should capture liberally around transitions.
436
+ `vk ai` does this automatically (see [AI](#ai--natural-language-tests)); when driving by
437
+ hand, `vk screenshot` around each screen change and leave the PNG in the report.
438
+
427
439
  ## How it works
428
440
 
429
441
  ```
@@ -8,6 +8,11 @@ const ir_1 = require("./ir");
8
8
  const describe = (leaf) => [leaf.command, ...leaf.positionals, ...leaf.flags.map((f) => (f.value === 'true' ? `--${f.name}` : `--${f.name} ${f.value}`))]
9
9
  .join(' ')
10
10
  .trim();
11
+ /** A screenshot leaf is best-effort review evidence, not a gate. The `vk ai`
12
+ * grammar has the model sprinkle them around transitions, so a capture that
13
+ * fails (a device hiccup on screencap) must never turn a green run red — see
14
+ * the guard in execLeaf. */
15
+ const isScreenshotLeaf = (leaf) => leaf.command === 'screenshot' || leaf.command === 'shot';
11
16
  /** A structural fingerprint of the screen: sorted id+text+type set. Used for the
12
17
  * loop no-progress check — deliberately NOT the raw hierarchy (its node ordering
13
18
  * is nondeterministic between identical states, which would false-trip). */
@@ -129,6 +134,19 @@ async function runPlan(plan, deps) {
129
134
  }
130
135
  if (outcome.code === 0)
131
136
  return { status: 'ok' };
137
+ // A review screenshot is best-effort evidence, never a gate. The grammar has the
138
+ // model insert them liberally around transitions, so a capture that fails (a
139
+ // device hiccup on screencap) must not fail an otherwise-green run. Log it,
140
+ // downgrade the just-recorded failed step to a clean pass (markLastStepHealed
141
+ // sets status=passed/exitCode=0 and drops the failure evidence) so the report and
142
+ // JUnit stay consistent with the green run, then continue. Scoped to screenshot/
143
+ // shot — every other command's failure stays terminal.
144
+ if (isScreenshotLeaf(current)) {
145
+ const why = outcome.error ? outcome.error.message.split('\n')[0] : `exited ${outcome.code}`;
146
+ deps.log(`[ai] ${where}: screenshot capture failed (${why}) — continuing (best-effort review screenshot)`);
147
+ deps.markHealed?.(`screenshot capture failed (${why}) — skipped (best-effort)`);
148
+ return { status: 'ok' };
149
+ }
132
150
  if (isHealable(outcome)) {
133
151
  return { status: 'fail', where, reason: `unresolved after ${maxRepairs} repair attempt(s): ${outcome.error.message.split('\n')[0]}` };
134
152
  }
@@ -54,7 +54,12 @@ RULES:
54
54
  - assert is for VERIFICATION only and is terminal — never use it as a step you expect to
55
55
  fail. Put genuinely-optional UI behind if-present.
56
56
  - Prefer resource-id / accessibility selectors over visible text where possible.
57
- - Translate the test literally and minimally; do not invent steps the prose does not imply.`;
57
+ - Translate the test literally and minimally: do not invent ACTION steps (tap/text/swipe/key/assert)
58
+ the prose does not imply. The ONE exception is screenshot — insert screenshot steps liberally as
59
+ post-run review evidence: after each screen transition (launch, a navigation tap, a submit, a
60
+ swipe/scroll) AND inside if-present/repeat bodies, so a failing branch or loop iteration is visible
61
+ in the report. Screenshots never affect the result; err toward too many. They are dumped into the
62
+ report for humans and never read back, so they are free on replay.`;
58
63
  exports.REPAIR_GRAMMAR = `A single step in a verikun plan failed to resolve its selector against the live screen
59
64
  (shown below). Decide between two outcomes — and be STRICT:
60
65
 
package/dist/version.js CHANGED
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // GENERATED by scripts/gen-version.mjs from package.json's "version" at build time
5
5
  // (the `prebuild` script). Do NOT edit by hand; bump package.json instead.
6
- exports.VERSION = '0.7.0';
6
+ exports.VERSION = '0.8.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verikun",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Drive Android emulators/devices and iOS simulators for AI agents: tap, type, swipe, screenshot, and inspect the UI hierarchy by semantic identifiers — like Puppeteer for native apps.",
5
5
  "keywords": [
6
6
  "android",