@bastani/atomic 0.9.56-alpha.1 → 0.9.57-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/CHANGELOG.md +24 -0
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/subagents/skills/agent-desktop/SKILL.md +83 -0
  7. package/dist/builtin/web-access/package.json +1 -1
  8. package/dist/builtin/workflows/CHANGELOG.md +12 -0
  9. package/dist/builtin/workflows/builtin/adversarial-verification.js +3 -3
  10. package/dist/builtin/workflows/builtin/{chunk-49kkbdpr.js → chunk-2f1shjah.js} +1 -1
  11. package/dist/builtin/workflows/builtin/{chunk-dcxscfnb.js → chunk-37gm3bzk.js} +1 -1
  12. package/dist/builtin/workflows/builtin/{chunk-2jfst7e4.js → chunk-45fn5q5p.js} +1 -1
  13. package/dist/builtin/workflows/builtin/{chunk-hx8v4p97.js → chunk-4ek3v2wm.js} +1 -1
  14. package/dist/builtin/workflows/builtin/{chunk-z3pajrfs.js → chunk-8d40nyz9.js} +1 -1
  15. package/dist/builtin/workflows/builtin/{chunk-qhm35ntx.js → chunk-g3b2zf8r.js} +2 -2
  16. package/dist/builtin/workflows/builtin/{chunk-6jpwc09k.js → chunk-h6bt0r0g.js} +2 -2
  17. package/dist/builtin/workflows/builtin/{chunk-9cm2ckq2.js → chunk-x25rjw4y.js} +4 -4
  18. package/dist/builtin/workflows/builtin/{chunk-apagcs4r.js → chunk-xqcy5nve.js} +1 -1
  19. package/dist/builtin/workflows/builtin/{chunk-w4xp1w1f.js → chunk-yb55w6me.js} +1 -1
  20. package/dist/builtin/workflows/builtin/{chunk-k5q3t7je.js → chunk-yjgfnbgd.js} +1 -1
  21. package/dist/builtin/workflows/builtin/classify-and-act.js +3 -3
  22. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +3 -3
  23. package/dist/builtin/workflows/builtin/generate-and-filter.js +3 -3
  24. package/dist/builtin/workflows/builtin/goal.js +3 -3
  25. package/dist/builtin/workflows/builtin/index.js +11 -11
  26. package/dist/builtin/workflows/builtin/loop-until-done.js +3 -3
  27. package/dist/builtin/workflows/builtin/open-claude-design.js +3 -3
  28. package/dist/builtin/workflows/builtin/ralph.js +3 -3
  29. package/dist/builtin/workflows/builtin/steering-context.js +1 -1
  30. package/dist/builtin/workflows/builtin/tournament.js +3 -3
  31. package/dist/builtin/workflows/package.json +1 -1
  32. package/dist/builtin/workflows/src/extension/index.bundle.mjs +7 -7
  33. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +4 -4
  34. package/dist/builtin/workflows/src/index.js +4 -4
  35. package/dist/builtin/workflows/src/local-worker-entry.mjs +4 -4
  36. package/dist/core/system-prompt.d.ts.map +1 -1
  37. package/dist/core/system-prompt.js +2 -3
  38. package/dist/core/system-prompt.js.map +1 -1
  39. package/docs/computer-use.md +119 -98
  40. package/docs/getting-started/first-session.md +1 -1
  41. package/docs/skills.md +2 -2
  42. package/docs/usage.md +1 -1
  43. package/docs/workflows/authoring.md +105 -141
  44. package/docs/workflows/verification.md +14 -13
  45. package/npm-shrinkwrap.json +32 -32
  46. package/package.json +3 -3
  47. package/dist/builtin/subagents/skills/cua-driver/BROWSER.md +0 -562
  48. package/dist/builtin/subagents/skills/cua-driver/EMBEDDING.md +0 -685
  49. package/dist/builtin/subagents/skills/cua-driver/LINUX.md +0 -412
  50. package/dist/builtin/subagents/skills/cua-driver/MACOS.md +0 -996
  51. package/dist/builtin/subagents/skills/cua-driver/README.md +0 -123
  52. package/dist/builtin/subagents/skills/cua-driver/RECORDING.md +0 -132
  53. package/dist/builtin/subagents/skills/cua-driver/RUNTIME.md +0 -115
  54. package/dist/builtin/subagents/skills/cua-driver/SKILL.md +0 -108
  55. package/dist/builtin/subagents/skills/cua-driver/VISUAL.md +0 -125
  56. package/dist/builtin/subagents/skills/cua-driver/WINDOWS.md +0 -832
  57. package/dist/builtin/subagents/skills/cua-driver/WORKFLOW.md +0 -226
@@ -519,169 +519,96 @@ After exit is selected, new tracked work and retained stage operations are refus
519
519
 
520
520
  On resume of an unfinished tool, a successful exit cannot skip that tool. Restore its matching call before new tracked work; otherwise Atomic reports `insufficient_state: replay topology mismatch`. Intentional failed, blocked, cancelled, or skipped exits remain available.
521
521
 
522
- <a id="desktop-verification-with-cua-driver-in-ctx-tool" />
522
+ <a id="desktop-verification-with-agent-desktop-in-ctx-tool" />
523
523
 
524
- ### Desktop verification with Cua Driver in `ctx.tool`
524
+ ### Desktop verification with agent-desktop in `ctx.tool`
525
525
 
526
- When a model chooses each desktop action, an authored model stage loads the bundled `cua-driver` skill and runs one-shot `cua-driver call <tool>` commands; see [Computer use](/computer-use#desktop-automation-with-cua-driver) for the face rule, installation, telemetry, and readiness. When your workflow's TypeScript owns the sequence and the postcondition, run the scenario with the [`@trycua/cua-driver`](https://www.npmjs.com/package/@trycua/cua-driver) TypeScript SDK inside `ctx.tool(name, args, fn, { timeoutMs })` so the observe → act → re-observe → assert loop is a durable, replayable node rather than a transcript.
526
+ When a model chooses each desktop action, an authored model stage loads the bundled `agent-desktop` skill and runs one-shot `agent-desktop` commands; see [Computer use](/computer-use#desktop-automation-with-agent-desktop) for the rule, installation, and readiness. When your workflow's TypeScript owns the sequence and the postcondition, call the `agent-desktop` CLI from inside `ctx.tool(name, args, fn, { timeoutMs })` so the observe → act → verify loop is a durable, replayable node rather than a transcript. agent-desktop has no TypeScript SDK: every command prints one JSON envelope (`ok`, then `data` or `error`), and that envelope is the contract.
527
527
 
528
- Prerequisites and setup, each as one bounded attempt:
528
+ The only prerequisite is the CLI on the host: `npm install -g agent-desktop` (Node 18 or later), approving its install script if npm blocks it. Do not install it from inside the run. The readiness preflight below reports a missing install as a limitation instead. The executable carries its own guides (`agent-desktop skills get desktop`), and Atomic bundles the skill, so skip `npx skills add` and leave existing user-level skills alone.
529
529
 
530
- - `node` (preferred) or `bun` on the host. If neither is present, install one in a bounded attempt (Node via [fnm](https://github.com/Schniz/fnm) with `fnm install --lts` or the host's package manager, Bun via `curl -fsSL https://bun.sh/install | bash`) and report what the installer did; if the install is refused or fails, report that as the limitation rather than retrying.
531
- - The `cua-driver` executable (`cua-driver --version`), installed with upstream's one-line installer if missing, followed by `cua-driver telemetry disable` once.
532
- - The SDK installed at the exact driver version into a scratch directory outside the user's repository, for example `npm install @trycua/cua-driver@0.36.0 --prefix ~/.cache/atomic-cua`. The package ships per-platform native optional dependencies. Daemon-backed clients verify contract, tool-schema, capability, and protocol versions before each action and refuse on mismatch, so the pin must match `cua-driver --version`.
530
+ The workflow below checks readiness in its own `ctx.tool` first, so a missing install, a missing macOS permission, or an unreachable Linux accessibility bus ends the run with `ctx.exit({ status: "blocked", reason })`. A blocked author exit is terminal and not resumable (see [Early exit with `ctx.exit()`](#early-exit-with-ctx-exit)), and the preflight's `{ ready: false }` result is a completed, cached checkpoint, so after the user fixes the problem start a new run: its fresh preflight checks again instead of replaying the cached result. The scenario tool spawns one `agent-desktop` process per command without a shell (on Windows it starts the package's native executable, not npm's `.cmd` shim, so no argument is parsed by `cmd.exe`), saves each result's JSON and both screenshots as evidence, forwards `signal` so a quit or targeted abort kills the child, and throws anything but `verified`, so a failed scenario fails the node.
533
531
 
534
- The executable installer does not install an agent skill. Atomic bundles the skill, so skip upstream's optional `cua-driver skills install`, `cua-driver skills update`, and `clawhub install @cua/driver` steps; leave existing user-level skills alone.
535
-
536
- The scenario itself is a small script in that scratch directory. It acquires the driver with `CuaDriver.connect(undefined)` when a daemon is running, so it reuses the daemon's permission identity (on macOS, `CuaDriver.app`'s Accessibility and Screen Recording grants) and the persisted telemetry-off preference; upstream describes `connect()` as a compatibility and app-hosting path, which is exactly the role it plays here. Only when no daemon is reachable does it fall back to `CuaDriver.create(undefined)`, which loads the runtime into the node process. On macOS that in-process fallback attributes permissions to the node host, normally the terminal app, as a **separate grant** from the app's; `checkPermissions` is then read-only, and the host must fully quit and relaunch after granting. Save it as `~/.cache/atomic-cua/verify-counter.mjs`:
537
-
538
- ```js
539
- // Reads {"daemon":true|false,"artifactsDir":"..."} from argv[2]; prints one JSON result line.
540
- // Replace the app name, window title, element labels, and postcondition with ones you control.
532
+ ```ts
533
+ import { execFileSync, spawn } from "node:child_process";
541
534
  import { mkdirSync, writeFileSync } from "node:fs";
542
535
  import { join } from "node:path";
543
- import {
544
- ActionTarget, ClickButton, ClickInput, ClickPosition, CuaDriver,
545
- GetWindowStateInput, InputDeliveryMode, ListAppsInput, ListWindowsInput,
546
- } from "@trycua/cua-driver";
547
-
548
- const { daemon, artifactsDir } = JSON.parse(process.argv[2]);
549
- mkdirSync(artifactsDir, { recursive: true });
550
- const unique = (items, what) => {
551
- if (items.length !== 1) throw new Error(`Expected one ${what}, found ${items.length}`);
552
- return items[0];
553
- };
554
- const finish = (result, detail) => {
555
- process.stdout.write(`${JSON.stringify({ result, detail })}\n`);
556
- process.exitCode = result === "verified" ? 0 : 1;
557
- };
536
+ import { workflow } from "@bastani/atomic/workflows";
537
+ import { Type } from "typebox";
558
538
 
559
- // The wrapper already set CUA_DRIVER_RS_TELEMETRY_ENABLED=false in this process's environment
560
- // before the driver was constructed; the SDK is one of the faces that reports telemetry by default.
561
- const driver = daemon ? CuaDriver.connect(undefined) : CuaDriver.create(undefined);
562
- try {
563
- const apps = await driver.listApps(ListAppsInput.new({}));
564
- const app = unique(apps.apps.filter((a) => a.name === "Window Demo" && a.running), "app");
565
- const windows = await driver.listWindows(ListWindowsInput.new({ pid: app.pid, onScreenOnly: true }));
566
- const window = unique(windows.windows.filter((w) => w.title === "Counter"), "window");
567
- const target = new ActionTarget.Window({ pid: app.pid, windowId: window.windowId });
568
- const snapshot = async (label) => {
569
- const state = await driver.getWindowState(
570
- GetWindowStateInput.new({
571
- pid: app.pid, windowId: window.windowId,
572
- includeAccessibilityTree: true, includeScreenshot: true,
573
- screenshotOutFile: join(artifactsDir, `${label}.png`),
574
- }),
575
- );
576
- if (state.degraded || state.truncated) throw new Error(`${label} snapshot is degraded or truncated`);
577
- // Keep the whole result (snapshot id, screenshot reference, degraded/truncated flags), not just
578
- // the elements, so the retained tree is provably from a complete snapshot. Ids are bigint.
579
- const json = JSON.stringify(state, (_key, value) => (typeof value === "bigint" ? value.toString() : value), 2);
580
- writeFileSync(join(artifactsDir, `${label}.json`), json);
581
- return state;
539
+ type Envelope = {
540
+ ok: boolean;
541
+ data?: {
542
+ permissions?: Record<string, { state?: string }>;
543
+ supported_surfaces?: string[];
544
+ matches?: { ref_id?: string }[];
545
+ value?: string | null;
546
+ found?: boolean;
582
547
  };
548
+ error?: { code: string; message: string; disposition?: { delivery: string; retry: string } };
549
+ };
583
550
 
584
- const before = await snapshot("before");
585
- const button = unique((before.elements ?? []).filter((e) => e.label === "Increment"), "button");
586
- const counter = unique((before.elements ?? []).filter((e) => e.label === "Count"), "counter");
587
- if (!button.elementToken || counter.value === undefined) throw new Error("Snapshot lacks the button token or counter value");
588
-
589
- let clicked = false;
590
- try {
591
- await driver.click(ClickInput.new({
592
- target,
593
- position: new ClickPosition.Element({ elementToken: button.elementToken }),
594
- deliveryMode: InputDeliveryMode.Background,
595
- button: ClickButton.Left, count: 1,
596
- }));
597
- clicked = true;
598
- } catch (error) {
599
- // A timeout or interrupted action before its response is "unknown": the postcondition below
600
- // decides, and the click is never replayed.
601
- if (!/timed out|ActionInterrupted/u.test(String(error))) throw error;
602
- }
603
-
604
- // Bounded poll on fresh snapshots; never a fixed sleep, never a second click.
605
- const deadline = Date.now() + 10_000;
606
- let after = await snapshot("after");
607
- let updated = unique((after.elements ?? []).filter((e) => e.label === "Count"), "counter");
608
- while (updated.value === counter.value && Date.now() < deadline) {
609
- await new Promise((resolve) => setTimeout(resolve, 250));
610
- after = await snapshot("after");
611
- updated = unique((after.elements ?? []).filter((e) => e.label === "Count"), "counter");
612
- }
613
- if (updated.value !== undefined && updated.value !== counter.value) {
614
- finish("verified", `Count ${counter.value} -> ${updated.value}`);
615
- } else {
616
- finish(clicked ? "refuted" : "unknown", `Count stayed ${counter.value}`);
617
- }
618
- } catch (error) {
619
- finish("unknown", String(error));
620
- } finally {
621
- try {
622
- await driver.shutdown();
623
- } finally {
624
- if ("uniffiDestroy" in driver && typeof driver.uniffiDestroy === "function") driver.uniffiDestroy();
625
- }
551
+ // On Windows npm's `agent-desktop` command is a .cmd shim that only runs through cmd.exe, which
552
+ // would split an argument at a space and run whatever follows an `&`. Start the native executable
553
+ // the package ships instead, so Node passes every argument literally.
554
+ function agentDesktopCommand(): string {
555
+ if (process.platform !== "win32") return "agent-desktop";
556
+ const root = execFileSync("npm", ["root", "-g"], { encoding: "utf8", shell: true }).trim();
557
+ return join(root, "agent-desktop", "bin", `agent-desktop-win32-${process.arch}.exe`);
626
558
  }
627
- ```
628
559
 
629
- The workflow runs a readiness preflight as its own `ctx.tool` first, so a missing permission or session ends the run with `ctx.exit({ status: "blocked", reason })`. A blocked author exit is terminal and not resumable (see [Early exit with `ctx.exit()`](#early-exit-with-ctx-exit)), and the preflight's `{ ready: false }` result is a completed, cached checkpoint, so after the user grants the permission start a new run: its fresh preflight checks again instead of replaying the cached result. The scenario tool spawns `node` with `CUA_DRIVER_RS_TELEMETRY_ENABLED=false` in the child environment, forwards `signal` so a quit or targeted abort kills the child, and maps anything but `verified` to a nonzero outcome:
630
-
631
- ```ts
632
- import { spawn } from "node:child_process";
633
- import { homedir } from "node:os";
634
- import { join } from "node:path";
635
- import { workflow } from "@bastani/atomic/workflows";
636
- import { Type } from "typebox";
637
-
638
- const sdkDir = join(homedir(), ".cache", "atomic-cua");
639
- const cuaEnv = { ...process.env, CUA_DRIVER_RS_TELEMETRY_ENABLED: "false" };
640
-
641
- function run(command: string, args: string[], signal: AbortSignal, cwd?: string) {
642
- return new Promise<{ code: number | null; stdout: string; stderr: string }>((resolve) => {
643
- const child = spawn(command, args, { cwd, env: cuaEnv, signal, stdio: ["ignore", "pipe", "pipe"] });
560
+ // One process per command, never through a shell. Every command prints one JSON envelope; branch
561
+ // on `ok`, `error.code` and `disposition`, never on message text.
562
+ function agentDesktop(args: string[], signal: AbortSignal) {
563
+ return new Promise<Envelope>((resolve) => {
564
+ const child = spawn(agentDesktopCommand(), args, { signal, stdio: ["ignore", "pipe", "pipe"] });
644
565
  let stdout = "";
645
566
  let stderr = "";
646
567
  child.stdout.on("data", (chunk: Buffer) => { stdout += chunk.toString(); });
647
568
  child.stderr.on("data", (chunk: Buffer) => { stderr += chunk.toString(); });
648
- // A missing executable (ENOENT) or an abort arrives here rather than on "close"; treat it as a
569
+ // A missing executable (ENOENT) or an abort arrives here rather than on "close"; report it as a
649
570
  // failed command so the preflight can return its remediation instead of throwing.
650
- child.on("error", (error) => resolve({ code: null, stdout, stderr: `${stderr}${error.message}` }));
651
- child.on("close", (code) => resolve({ code, stdout, stderr }));
571
+ child.on("error", (error) =>
572
+ resolve({ ok: false, error: { code: "SPAWN_FAILED", message: error.message } }));
573
+ child.on("close", () => {
574
+ try {
575
+ resolve(JSON.parse(stdout) as Envelope);
576
+ } catch {
577
+ resolve({ ok: false, error: { code: "NO_ENVELOPE", message: stderr.trim() || stdout.trim() } });
578
+ }
579
+ });
652
580
  });
653
581
  }
654
582
 
655
583
  export default workflow({
656
584
  name: "verify-counter",
657
585
  description: "Prove the Increment button changes the Count field in the Counter window.",
658
- inputs: { artifactsDir: Type.String({ description: "Directory for before/after state JSON and screenshots" }) },
586
+ inputs: { artifactsDir: Type.String({ description: "Directory for before/after screenshots" }) },
659
587
  outputs: { result: Type.String(), detail: Type.String() },
660
588
  run: async (ctx) => {
661
589
  const preflight = await ctx.tool(
662
- "cua-preflight",
590
+ "agent-desktop-preflight",
663
591
  { platform: process.platform },
664
592
  async ({ signal }) => {
665
- const version = await run("cua-driver", ["--version"], signal);
666
- if (version.code !== 0) {
667
- return { ready: false, reason: "cua-driver is not installed; run /bin/bash -c \"$(curl -fsSL https://cua.ai/driver/install.sh)\" (Windows: irm https://cua.ai/driver/install.ps1 | iex), then cua-driver telemetry disable" };
593
+ const version = await agentDesktop(["version"], signal);
594
+ if (!version.ok) {
595
+ return { ready: false, reason: "agent-desktop is not installed or not on PATH; run `npm install -g agent-desktop` (approve its install script if npm blocks it), then `agent-desktop version`" };
668
596
  }
669
- const status = await run("cua-driver", ["status"], signal);
670
- const daemon = status.code === 0;
671
- if (process.platform === "darwin" && daemon) {
672
- const permissions = await run("cua-driver", ["permissions", "status", "--json"], signal);
673
- const grants = permissions.code === 0
674
- ? (JSON.parse(permissions.stdout) as { accessibility?: boolean; screen_recording?: boolean })
675
- : {};
676
- if (grants.accessibility !== true || grants.screen_recording !== true) {
677
- return { ready: false, reason: "Missing macOS grant: run `cua-driver permissions grant`, toggle CuaDriver on under System Settings → Privacy & Security → Accessibility and Screen & System Audio Recording, then relaunch the daemon with `open -n -g -a CuaDriver --args serve`" };
597
+ const status = await agentDesktop(["status"], signal);
598
+ if (!status.ok) {
599
+ return { ready: false, reason: `agent-desktop status failed: ${status.error?.message ?? "no envelope"}` };
600
+ }
601
+ const permissions = status.data?.permissions ?? {};
602
+ for (const name of ["accessibility", "screen_recording"] as const) {
603
+ const state = permissions[name]?.state;
604
+ if (state !== "granted" && state !== "not_required") {
605
+ return { ready: false, reason: `Missing ${name} permission (${state}): run \`agent-desktop permissions --guide\` and have the user grant it to the app that launches the command` };
678
606
  }
679
607
  }
680
- const apps = await run("cua-driver", ["call", "list_apps"], signal);
681
- if (apps.code !== 0) {
682
- return { ready: false, reason: `cua-driver call list_apps failed; start the daemon (macOS: open -n -g -a CuaDriver --args serve; Windows: cua-driver serve in the interactive session; Linux: cua-driver serve inside the graphical session): ${apps.stderr.trim()}` };
608
+ if (!status.data?.supported_surfaces?.length) {
609
+ return { ready: false, reason: "No readable surfaces: run inside the user's graphical session with a running AT-SPI bus, then rerun `agent-desktop status`" };
683
610
  }
684
- return { ready: true, daemon };
611
+ return { ready: true };
685
612
  },
686
613
  { timeoutMs: 60_000 },
687
614
  );
@@ -691,17 +618,54 @@ export default workflow({
691
618
 
692
619
  const scenario = await ctx.tool(
693
620
  "verify-counter-scenario",
694
- { artifactsDir: ctx.inputs.artifactsDir, daemon: preflight.daemon },
621
+ { artifactsDir: ctx.inputs.artifactsDir },
695
622
  async ({ signal }) => {
696
- const args = JSON.stringify({ daemon: preflight.daemon, artifactsDir: ctx.inputs.artifactsDir });
697
- const child = await run("node", ["verify-counter.mjs", args], signal, sdkDir);
698
- const line = child.stdout.trim().split("\n").at(-1) ?? "";
699
- const parsed = line.startsWith("{") ? (JSON.parse(line) as { result: string; detail: string }) : undefined;
700
- const result = parsed?.result ?? "unknown";
701
- if (result !== "verified") {
702
- throw new Error(`desktop verification ${result}: ${parsed?.detail ?? child.stderr.trim()}`);
623
+ // Replace the app name, element names, and postcondition with ones you control.
624
+ const app = "Window Demo";
625
+ mkdirSync(ctx.inputs.artifactsDir, { recursive: true });
626
+ // Keep every result as evidence beside the screenshots, and fail rather than report
627
+ // `verified` when a piece of evidence is missing.
628
+ const save = (step: string, envelope: Envelope) => {
629
+ writeFileSync(join(ctx.inputs.artifactsDir, `${step}.json`), JSON.stringify(envelope, null, 2));
630
+ return envelope;
631
+ };
632
+ const capture = async (step: string) => {
633
+ const shot = save(step, await agentDesktop(["screenshot", "--app", app, join(ctx.inputs.artifactsDir, `${step}.png`)], signal));
634
+ if (!shot.ok) throw new Error(`Could not capture the ${step} screenshot: ${shot.error?.code ?? "no envelope"}`);
635
+ };
636
+ const one = async (role: string, name: string) => {
637
+ const found = await agentDesktop(["find", "--app", app, "--role", role, "--name", name, "--exact", "--limit", "2"], signal);
638
+ const matches = found.data?.matches ?? [];
639
+ if (!found.ok || matches.length !== 1 || !matches[0].ref_id) {
640
+ throw new Error(`Expected one ${role} named ${name}: ${found.error?.code ?? `${matches.length} matches`}`);
641
+ }
642
+ return matches[0].ref_id;
643
+ };
644
+
645
+ const button = await one("button", "Increment");
646
+ const field = await one("textfield", "Count");
647
+ const read = save("read-before", await agentDesktop(["get", field, "--property", "value"], signal));
648
+ const before = Number(read.data?.value);
649
+ if (!read.ok || Number.isNaN(before)) throw new Error("Count has no numeric value to start from");
650
+ await capture("before");
651
+
652
+ // Act once. An error whose disposition is `retry: "safe"` changed nothing, so the node fails
653
+ // and a new run starts fresh; any other failure may have landed, so the wait below decides.
654
+ const click = save("click", await agentDesktop(["click", button], signal));
655
+ const notDelivered = click.error?.disposition?.retry === "safe";
656
+ if (!click.ok && notDelivered) throw new Error(`Click was not delivered: ${click.error?.code}`);
657
+
658
+ // Verify with a bounded wait on the postcondition, never a sleep and never a second click.
659
+ const expected = String(before + 1);
660
+ const waited = save("wait", await agentDesktop(["wait", "--element", field, "--predicate", "value", "--value", expected, "--timeout", "10000"], signal));
661
+ await capture("after");
662
+ if (waited.ok && waited.data?.found) {
663
+ return { result: "verified", detail: `Count ${before} -> ${expected}; evidence in ${ctx.inputs.artifactsDir}` };
703
664
  }
704
- return { result, detail: parsed?.detail ?? "" };
665
+ // A click that errored without a safe disposition, or a wait that timed out, is not proof
666
+ // either way: report it as unknown or refuted and let the next run start from fresh state.
667
+ const result = click.ok ? "refuted" : "unknown";
668
+ throw new Error(`desktop verification ${result}: Count did not become ${expected} (${waited.error?.code ?? "no match"})`);
705
669
  },
706
670
  { timeoutMs: 5 * 60_000 },
707
671
  );
@@ -711,7 +675,7 @@ export default workflow({
711
675
  });
712
676
  ```
713
677
 
714
- A `verified` result is cached durably, so a resumed run does not click again. A thrown `refuted`, `blocked`, or `unknown` result fails the node and is not replayed from cache; a new run executes the preflight and the scenario again from a fresh snapshot, and a durable retry of a resumable failure replays the completed preflight checkpoint and re-runs only the scenario. Keep the artifacts directory outside the repository unless the evidence belongs in the deliverable, and never post the installation UUID from `cua-driver telemetry status` in a result or reason. Safety is the same on both faces: one controller per desktop, a dedicated session or account where practical, and an explicit stopping point before destructive or publishing actions.
678
+ A `verified` result is cached durably, so a resumed run does not click again. A thrown `refuted` or `unknown` result fails the node and is not replayed from cache; a new run executes the preflight and the scenario again from fresh refs, and a durable retry of a resumable failure replays the completed preflight checkpoint and re-runs only the scenario. Refs belong to the snapshot that produced them, so look an element up again after any UI change instead of reusing a ref from an earlier step. Keep the artifacts directory outside the repository unless the evidence belongs in the deliverable. Safety is the same on both paths: one controller per desktop, a dedicated session or account where practical, and an explicit stopping point before destructive or publishing actions.
715
679
 
716
680
  ### Classifier and image models in `ctx.tool`
717
681
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Verify the behavior that changed, then give the reviewer enough evidence to understand the result. A small fix may need a focused test and a short explanation. An interactive change usually needs a real user scenario as well. A video is useful when it shows something a test log or screenshot cannot; it is not required for every PR.
4
4
 
5
- For tool installation, automation techniques, platform permissions, and general work in applications, read [Computer use](/computer-use). That guide covers Herdr for terminals, agent-browser for browsers, Mobile Safari, and CDP-exposing apps, and Cua Driver for other desktop, simulator, and emulator CUA on macOS, Linux, and Windows. It also covers native accessibility and application tools when they are easier or more reliable.
5
+ For tool installation, automation techniques, platform permissions, and general work in applications, read [Computer use](/computer-use). That guide covers Herdr for terminals, agent-browser for browsers, Mobile Safari, and CDP-exposing apps, and agent-desktop for native desktop apps and OS dialogs on macOS, Linux, and Windows. It also covers native accessibility and application tools when they are easier or more reliable.
6
6
 
7
7
  <a id="select-the-verification-environment" />
8
8
 
@@ -13,12 +13,13 @@ Start with the project's existing tests, build, typecheck, and lint commands. Ad
13
13
  | Changed behavior | Preferred mechanism | What to check |
14
14
  | --- | --- | --- |
15
15
  | Interactive terminal or TUI | **Herdr**, under its explicit-request and managed-pane requirements; tmux or native Windows psmux as fallbacks | Actual input, rendered output, navigation, resizing, and exit behavior relevant to the change. |
16
- | Browser/frontend in Chrome/Chromium, Mobile Safari in the iOS Simulator, Electron desktop app or another CDP-exposing app, Slack, or cloud browser | **agent-browser**, for everything in [its scope](/computer-use#what-agent-browser-covers); Cua Driver when agent-browser hits a limitation | The user flow and its visible result, with DOM or network assertions where useful. |
17
- | Native desktop app, native iOS app in the iOS Simulator, Android emulator, desktop Safari or another non-Chromium browser, or OS dialogs | **Cua Driver**: the `cua-driver` CLI through the bundled skill when a model chooses actions, or the `@trycua/cua-driver` SDK inside `ctx.tool` when workflow code owns the scenario; supplemented by native/app APIs | The exact window's before/after accessibility state and screenshots, a checked postcondition, and the saved or exported result. |
16
+ | Browser/frontend in Chrome/Chromium, Mobile Safari in the iOS Simulator, Electron desktop app or another CDP-exposing app, Slack, or cloud browser | **agent-browser**, for everything in [its scope](/computer-use#what-agent-browser-covers); agent-desktop when agent-browser hits a limitation | The user flow and its visible result, with DOM or network assertions where useful. |
17
+ | Native desktop app, menus and menu bars, desktop Safari or another non-Chromium browser, or OS dialogs and permission prompts | **agent-desktop**: the bundled `agent-desktop` skill and one-shot `agent-desktop` commands when a model chooses actions, or the `agent-desktop` CLI called from `ctx.tool` when workflow code owns the scenario; supplemented by native/app APIs | The exact app's before/after accessibility state from the JSON results, screenshots, a checked postcondition, and the saved or exported result. |
18
+ | Native iOS app in the Simulator or Android app in an emulator | **Native mobile tooling**: `xcrun simctl`, Appium with XCUITest, or `adb` with UI Automator. agent-desktop sees a simulator or emulator only as a desktop window ([coverage and limits](/computer-use#coverage-and-limits)) | The device or emulator actually exercised, its screenshots or recording, and the checked postcondition. |
18
19
  | API, library, script, or other non-UI behavior | Existing test runner and shell commands | Inputs, outputs, error handling, and relevant build/type contracts. |
19
20
  | Documentation | Documentation checks and example review | Links, navigation, command accuracy, and whether a reader can follow the instructions. |
20
21
 
21
- See [tool selection](/computer-use#choose-the-right-tool) before operating a session. Reach for agent-browser first whenever the target is in its scope: its text snapshots cost far fewer tokens than screenshot-driven CUA. Herdr is the terminal priority, but the preference does not authorize control from outside a Herdr-managed pane. Install missing tools when permitted; otherwise use the available fallback and describe any coverage gap.
22
+ See [tool selection](/computer-use#choose-the-right-tool) before operating a session. Reach for agent-browser first whenever the target is in its scope: its text snapshots cost far fewer tokens than desktop accessibility trees and screenshots. Herdr is the terminal priority, but the preference does not authorize control from outside a Herdr-managed pane. Install missing tools when permitted; otherwise use the available fallback and describe any coverage gap.
22
23
 
23
24
  ### Reuse past verification
24
25
 
@@ -26,7 +27,7 @@ When a shell tool is available, the agent records each check it ran or attempted
26
27
 
27
28
  ```text
28
29
  Assistant-verification: herdr terminal E2E passed: /tasks lists running tasks first at 80x24
29
- Assistant-verification: cua-driver unavailable: Accessibility permission not granted
30
+ Assistant-verification: agent-desktop unavailable: Accessibility permission not granted
30
31
  ```
31
32
 
32
33
  Before choosing checks for a change, the agent looks up these lines for comparable changes (for example with `git log --format='%h %s%n%(trailers:key=Assistant-verification)' -- <path>`) and reuses the commands and scenarios that proved them. A setup recorded as `unavailable` is not retried without a reason to expect a different result. Past records guide the choice; they do not replace the project's required checks. See [execution history](/usage#system-prompt-files) to turn these records off.
@@ -99,19 +100,19 @@ See [terminal setup and capture commands](/computer-use#terminal-automation-with
99
100
 
100
101
  <a id="desktop-safety" />
101
102
 
102
- ### Native desktop, simulator, and emulator changes
103
+ ### Native desktop changes
103
104
 
104
- Use Cua Driver in a dedicated graphical session, following [the desktop guide](/computer-use#desktop-automation-with-cua-driver). When a language model chooses each action, whether in an interactive session or in any workflow stage acting outside `ctx.tool`, load the bundled `cua-driver` skill and drive the exact window with one-shot `cua-driver call <tool>` commands, running every command with `CUA_DRIVER_RS_TELEMETRY_ENABLED=false`. When a custom workflow's TypeScript owns the scenario and its postcondition, run it with the `@trycua/cua-driver` SDK inside `ctx.tool` as shown in [workflow authoring](/workflows/authoring#desktop-verification-with-cua-driver-in-ctx-tool). Either way the loop is the same: snapshot the window with `get_window_state`, act through a snapshot-bound element token, take a fresh snapshot, and check a postcondition with a bounded poll deadline. Application APIs can still give the strongest assertion, for example checking a saved document through the app API after exercising the visible Save flow.
105
+ Use agent-desktop in a dedicated graphical session, following [the desktop guide](/computer-use#desktop-automation-with-agent-desktop). When a language model chooses each action, whether in an interactive session or in any workflow stage acting outside `ctx.tool`, load the bundled `agent-desktop` skill, read `agent-desktop skills get desktop` and `agent-desktop skills get platform`, and drive the app with one-shot `agent-desktop` commands. When a custom workflow's TypeScript owns the scenario and its postcondition, call the `agent-desktop` CLI from `ctx.tool` as shown in [workflow authoring](/workflows/authoring#desktop-verification-with-agent-desktop-in-ctx-tool). Either way the loop is the same: snapshot the app, act on a ref from that snapshot, then `wait` for the postcondition with a bounded timeout and read it back. Application APIs can still give the strongest assertion, for example checking a saved document through the app API after exercising the visible Save flow.
105
106
 
106
- Evidence is the structured window state plus screenshots, not a screenshot alone. Save each `get_window_state` JSON result and its `screenshot_out_file` image (before and after the action) to the artifacts directory, and state the postcondition that was checked. A `degraded` or `truncated` snapshot is a failed observation, not a reason to act.
107
+ Evidence is the structured accessibility state plus screenshots, not a screenshot alone. Save the JSON results of the snapshot, the action and the `wait` that verified it, and an `agent-desktop screenshot` before and after the action, to the artifacts directory, and state the postcondition that was checked. A snapshot whose `data.complete` is `false` is a partial observation: drill further before acting. An action result is not proof that the UI changed; only the read that follows is.
107
108
 
108
- Capture the actual application or simulator. A Chrome recording is not desktop or native iOS evidence, and an agent-browser `-p ios` session proves Mobile Safari behavior, not a native iOS app. Cua Driver can interact with a visible simulator/emulator window, but does not directly control an arbitrary physical phone. Use supported native tooling where needed, and name the device or emulator actually exercised.
109
+ Capture the actual application. A Chrome recording is not desktop or native iOS evidence, and an agent-browser `-p ios` session proves Mobile Safari behavior, not a native iOS app. agent-desktop sees an iOS Simulator or Android emulator only as a desktop window and may not see the simulated device's UI, so use native mobile tooling (`xcrun simctl`, Appium with XCUITest, or `adb` with UI Automator) for native mobile apps, and name the device or emulator actually exercised. If none is available, report the gap instead of claiming coverage.
109
110
 
110
- Missing readiness is a blocked finding, not a failure to work around. Before the first action the stage checks `cua-driver --version` (one bounded install attempt with upstream's one-line installer if it is missing, then `cua-driver telemetry disable`), `cua-driver status`, `cua-driver doctor`, and `cua-driver call list_apps`, plus `cua-driver permissions status` on macOS. A builtin Goal or Ralph stage reports a missing macOS Accessibility or Screen Recording grant, a non-interactive Windows session, no graphical Linux session, or a refused or failed install as `blocked`/`needs_human` with the exact remediation (for macOS: `cua-driver permissions grant`, toggle CuaDriver on under System Settings → Privacy & Security → Accessibility and Screen & System Audio Recording, then relaunch the daemon with `open -n -g -a CuaDriver --args serve`), and re-runs the readiness check when the run resumes. A custom workflow does the same from a preflight `ctx.tool` that calls `ctx.exit({ status: "blocked", reason })`. Unlike a builtin stage, a blocked author exit is terminal and not resumable: after the user grants the permission, start a new run, whose fresh preflight checks again rather than replaying a cached result.
111
+ Missing readiness is a blocked finding, not a failure to work around. Before the first action the stage checks `agent-desktop version` (one bounded `npm install -g agent-desktop` attempt if it is missing, approving the package's install script when npm blocks it) and `agent-desktop status`. A builtin Goal or Ralph stage reports a missing macOS Accessibility permission (or Screen Recording when it needs screenshots), a non-interactive Windows session, no graphical Linux session with a running AT-SPI bus (an empty `supported_surfaces`), or a refused or failed install as `blocked`/`needs_human` with the exact remediation (for macOS: `agent-desktop permissions --guide`, then grant the terminal or editor that launches the command), and re-runs `agent-desktop status` when the run resumes. A custom workflow does the same from a preflight `ctx.tool` that calls `ctx.exit({ status: "blocked", reason })`. Unlike a builtin stage, a blocked author exit is terminal and not resumable: after the user grants the permission, start a new run, whose fresh preflight checks again rather than replaying a cached result.
111
112
 
112
- The executable installer does not install an agent skill. Atomic bundles the skill, so skip upstream's optional `cua-driver skills install`, `cua-driver skills update`, and `clawhub install @cua/driver` steps; leave existing user-level skills alone.
113
+ Atomic bundles the `agent-desktop` skill, so skip `npx skills add` for it, and leave existing user-level skills alone. The detailed guides come from the installed CLI (`agent-desktop skills get ...`), so they always match its version.
113
114
 
114
- Inspect saved files and exports rather than assuming a returned action means a completed operation. An action that times out before its response is `unknown`; resolve it with a fresh snapshot and the postcondition, never by replaying the action.
115
+ Inspect saved files and exports rather than assuming a returned action means a completed operation. Retry or substitute an action only when its `disposition.retry` is `safe`. An action that times out before its response, or whose delivery is anything but `not_delivered`, is `unknown`; resolve it with a fresh read and the postcondition, never by replaying the action.
115
116
 
116
117
  ## Use evidence in a workflow
117
118
 
@@ -156,7 +157,7 @@ Give the reviewer a short summary before linking logs or media. For example, rep
156
157
  - Limits: <checks/platforms not exercised>
157
158
  ```
158
159
 
159
- Attach a screenshot for a visual state, a short recording for an interaction, or logs for command behavior. When a run used Cua Driver, the evidence is the before/after `screenshot_out_file` PNGs from `get_window_state`, one pair per verified postcondition, with the window-state JSON kept locally and cited by name; when it used agent-browser, the evidence is its `screenshot` PNGs and `record` recordings (for an iOS Simulator session, its screenshots plus any `simctl` recording). Put them in the PR body next to the scenario they prove. Include reproduction steps even when media is available. Label local-only paths as local; reviewers cannot open a file on your machine. CI artifact links are useful when readers have access, but note retention limits where relevant.
160
+ Attach a screenshot for a visual state, a short recording for an interaction, or logs for command behavior. When a run used agent-desktop, the evidence is the before/after `agent-desktop screenshot` PNGs, one pair per verified postcondition, with the snapshot, action and `wait` JSON kept locally and cited by name; when it used agent-browser, the evidence is its `screenshot` PNGs and `record` recordings (for an iOS Simulator session, its screenshots plus any `simctl` recording). Put them in the PR body next to the scenario they prove. Include reproduction steps even when media is available. Label local-only paths as local; reviewers cannot open a file on your machine. CI artifact links are useful when readers have access, but note retention limits where relevant.
160
161
 
161
162
  Only upload to an authorized repository or destination. Inspect and redact secrets, personal information, private source content, and unrelated windows before attaching files. Permission to collect local evidence is not permission to publish it.
162
163
 
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.56-alpha.1",
3
+ "version": "0.9.57-alpha.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bastani/atomic",
9
- "version": "0.9.56-alpha.1",
9
+ "version": "0.9.57-alpha.1",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@bastani/atomic-natives": "0.9.56-alpha.1",
13
- "@bastani/pi-ai": "0.9.56-alpha.1",
12
+ "@bastani/atomic-natives": "0.9.57-alpha.1",
13
+ "@bastani/pi-ai": "0.9.57-alpha.1",
14
14
  "@earendil-works/pi-agent-core": "1.4.0",
15
15
  "@earendil-works/pi-codemode": "1.4.0",
16
16
  "@earendil-works/pi-tui": "1.4.0",
@@ -427,18 +427,18 @@
427
427
  }
428
428
  },
429
429
  "node_modules/@bastani/atomic-natives": {
430
- "version": "0.9.56-alpha.1",
431
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.56-alpha.1.tgz",
430
+ "version": "0.9.57-alpha.1",
431
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.57-alpha.1.tgz",
432
432
  "license": "MIT",
433
433
  "optionalDependencies": {
434
- "@bastani/atomic-natives-darwin-arm64": "0.9.56-alpha.1",
435
- "@bastani/atomic-natives-darwin-x64": "0.9.56-alpha.1",
436
- "@bastani/atomic-natives-linux-arm64-gnu": "0.9.56-alpha.1",
437
- "@bastani/atomic-natives-linux-arm64-musl": "0.9.56-alpha.1",
438
- "@bastani/atomic-natives-linux-x64-gnu": "0.9.56-alpha.1",
439
- "@bastani/atomic-natives-linux-x64-musl": "0.9.56-alpha.1",
440
- "@bastani/atomic-natives-win32-arm64-msvc": "0.9.56-alpha.1",
441
- "@bastani/atomic-natives-win32-x64-msvc": "0.9.56-alpha.1"
434
+ "@bastani/atomic-natives-darwin-arm64": "0.9.57-alpha.1",
435
+ "@bastani/atomic-natives-darwin-x64": "0.9.57-alpha.1",
436
+ "@bastani/atomic-natives-linux-arm64-gnu": "0.9.57-alpha.1",
437
+ "@bastani/atomic-natives-linux-arm64-musl": "0.9.57-alpha.1",
438
+ "@bastani/atomic-natives-linux-x64-gnu": "0.9.57-alpha.1",
439
+ "@bastani/atomic-natives-linux-x64-musl": "0.9.57-alpha.1",
440
+ "@bastani/atomic-natives-win32-arm64-msvc": "0.9.57-alpha.1",
441
+ "@bastani/atomic-natives-win32-x64-msvc": "0.9.57-alpha.1"
442
442
  },
443
443
  "engines": {
444
444
  "bun": ">=1.4.2",
@@ -446,8 +446,8 @@
446
446
  }
447
447
  },
448
448
  "node_modules/@bastani/atomic-natives-darwin-arm64": {
449
- "version": "0.9.56-alpha.1",
450
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.56-alpha.1.tgz",
449
+ "version": "0.9.57-alpha.1",
450
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.57-alpha.1.tgz",
451
451
  "license": "MIT",
452
452
  "os": [
453
453
  "darwin"
@@ -458,8 +458,8 @@
458
458
  "optional": true
459
459
  },
460
460
  "node_modules/@bastani/atomic-natives-darwin-x64": {
461
- "version": "0.9.56-alpha.1",
462
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.56-alpha.1.tgz",
461
+ "version": "0.9.57-alpha.1",
462
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.57-alpha.1.tgz",
463
463
  "license": "MIT",
464
464
  "os": [
465
465
  "darwin"
@@ -470,8 +470,8 @@
470
470
  "optional": true
471
471
  },
472
472
  "node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
473
- "version": "0.9.56-alpha.1",
474
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.56-alpha.1.tgz",
473
+ "version": "0.9.57-alpha.1",
474
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.57-alpha.1.tgz",
475
475
  "license": "MIT",
476
476
  "os": [
477
477
  "linux"
@@ -485,8 +485,8 @@
485
485
  "optional": true
486
486
  },
487
487
  "node_modules/@bastani/atomic-natives-linux-arm64-musl": {
488
- "version": "0.9.56-alpha.1",
489
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.56-alpha.1.tgz",
488
+ "version": "0.9.57-alpha.1",
489
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.57-alpha.1.tgz",
490
490
  "license": "MIT",
491
491
  "os": [
492
492
  "linux"
@@ -500,8 +500,8 @@
500
500
  "optional": true
501
501
  },
502
502
  "node_modules/@bastani/atomic-natives-linux-x64-gnu": {
503
- "version": "0.9.56-alpha.1",
504
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.56-alpha.1.tgz",
503
+ "version": "0.9.57-alpha.1",
504
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.57-alpha.1.tgz",
505
505
  "license": "MIT",
506
506
  "os": [
507
507
  "linux"
@@ -515,8 +515,8 @@
515
515
  "optional": true
516
516
  },
517
517
  "node_modules/@bastani/atomic-natives-linux-x64-musl": {
518
- "version": "0.9.56-alpha.1",
519
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.56-alpha.1.tgz",
518
+ "version": "0.9.57-alpha.1",
519
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.57-alpha.1.tgz",
520
520
  "license": "MIT",
521
521
  "os": [
522
522
  "linux"
@@ -530,8 +530,8 @@
530
530
  "optional": true
531
531
  },
532
532
  "node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
533
- "version": "0.9.56-alpha.1",
534
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.56-alpha.1.tgz",
533
+ "version": "0.9.57-alpha.1",
534
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.57-alpha.1.tgz",
535
535
  "license": "MIT",
536
536
  "os": [
537
537
  "win32"
@@ -542,8 +542,8 @@
542
542
  "optional": true
543
543
  },
544
544
  "node_modules/@bastani/atomic-natives-win32-x64-msvc": {
545
- "version": "0.9.56-alpha.1",
546
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.56-alpha.1.tgz",
545
+ "version": "0.9.57-alpha.1",
546
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.57-alpha.1.tgz",
547
547
  "license": "MIT",
548
548
  "os": [
549
549
  "win32"
@@ -554,8 +554,8 @@
554
554
  "optional": true
555
555
  },
556
556
  "node_modules/@bastani/pi-ai": {
557
- "version": "0.9.56-alpha.1",
558
- "resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.56-alpha.1.tgz",
557
+ "version": "0.9.57-alpha.1",
558
+ "resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.57-alpha.1.tgz",
559
559
  "license": "MIT",
560
560
  "dependencies": {
561
561
  "@anthropic-ai/sdk": "0.129.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.56-alpha.1",
3
+ "version": "0.9.57-alpha.1",
4
4
  "description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "atomicConfig": {
@@ -89,8 +89,8 @@
89
89
  "prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
90
90
  },
91
91
  "dependencies": {
92
- "@bastani/atomic-natives": "0.9.56-alpha.1",
93
- "@bastani/pi-ai": "0.9.56-alpha.1",
92
+ "@bastani/atomic-natives": "0.9.57-alpha.1",
93
+ "@bastani/pi-ai": "0.9.57-alpha.1",
94
94
  "@earendil-works/pi-agent-core": "1.4.0",
95
95
  "@earendil-works/pi-codemode": "1.4.0",
96
96
  "@earendil-works/pi-tui": "1.4.0",