The builder's approval check refused dev servers before looking at the safe build list. `npx vite build` is on that list, but it also starts with `npx vite` (a dev server), so it was refused as one, whatever the mode or Auto setting.
A listed build is no longer read as a dev server: `npx vite build` and `cd app && npx vite build` are allowed, while `npx vite` and `npx vite --host …` are still refused. A command in watch mode (`--watch`) is now refused with the same hint, since it never exits either. That includes a listed build such as `npx vite build --watch`. The safe-list match moved into one helper used by both checks.
**Verified:** new cases in the approval tests (three spellings of the build allowed; two server forms and a watch build refused). The engine's approval tests, clippy and fmt pass.
Fixes#291
The engine had its own `write_atomic` (used for `craft.json`, the inbox, reports and session files). Its temp file was named by process only, so two threads saving the same file at once wrote into one temp file. One rename then found it gone ("craft.json: No such file or directory"), and the file could end up with two versions mixed ("trailing characters").
The engine now uses the platform crate's `write_atomic`, which already gave each write its own temp file and kept the file's permissions. It also gains the engine's short retry when Windows briefly can't replace a file another program holds open. There is one atomic writer now; docs/pitfalls.md says so.
**Verified:**
- A new engine test: four threads each save one file 50 times and read it back. Every save succeeds, every read is one whole version, and no temp files are left. It fails against the old engine writer (checked) and passes now.
- The existing "file held open for a moment" test still passes.
- `cargo test -p craft-anything-engine` (397), the platform fs tests, clippy on both crates and fmt.
**Not covered:** two saves that overlap can still each start from what was on disk, so the later one wins for fields that aren't the person's (the person's fields are kept, as before). That's separate from the write itself.
Fixes#273
`android_package_show`'s summary, shown in CLI help and the MCP tool list, said "signatures are not verified". The tool does verify them: v2/v3 signatures over the signed data with a recomputed content digest, and v1 PKCS#7 with the per-file digests. Its own `verification_scope` limitation says so. The summary now says signatures and content digests are verified, but not whether the certificate is one you trust.
**Verified:** text only. `cargo xtask tools` leaves docs/tools.md unchanged, and fmt passes.
Fixes#247
`adb_screenshot_take`, `adb_bugreport_save`, `adb_file_download` and `adb_app_download` create their fresh `output_directory` first, then check adb and the device. A device that was offline (or a missing adb, or a failed pull) left that folder behind, empty. The retry the error recommends then failed with "already exists", without ever reaching adb.
These tools now hold the folder in a small guard (`UnlessWritten`, next to `create_absent_dir`). When the tool stops, the guard removes the folder only if nothing was written into it, so partial pulls stay. On success the tool keeps the folder.
**Verified:**
- A new test: the guard removes an empty folder, keeps one with a file in it and keeps one marked kept.
- The same test calls all four tools through the engine with adb missing: no folder is left, and the identical retry reaches the same adb error rather than "already exists". That half runs only where adb isn't installed, like the other adb tests; it was skipped here because adb is on this machine.
- `cargo test -p craft-anything-engine adb`, clippy, fmt.
**Not changed:** the website, web, firmware and packed tools create output folders the same way. They can take the guard if needed.
Fixes#234
`adb_app_show` treated `dumpsys package <name>` output as describing the package if it merely contained the name. Android's answer for a missing package, `Unable to find package: <name>`, contains the name, so the tool returned successful evidence with no fields and complete coverage.
It now requires that package's own `Package [<name>]` block and otherwise returns the existing `NotFound` error with the "List installed packages with adb_apps_list." remediation.
**Verified:** a unit test with Android's missing-package reply, another package's block and an installed package; `cargo test -p craft-anything-engine adb`, clippy, fmt.
**Not verified:** a run against a real device.
Fixes#235
A paused, stopped or failed build only offered Continue or Try again; there was no way to say "enough now". project_build_finish marks the project Ready and adds a Done step to its conversation, keeping everything; the project screen shows It's done beside Continue and Try again when nothing is running.
Fixes#210
web_site_open keeps its browser for one session, and each CLI command is a session of its own that closes its browser when it ends. From the CLI, a capture with no open site now says so, and to run the steps together in an MCP client, the app or rebuild. Documented in tool-status.
Fixes#153
project_play's help says that on Windows a started program inherits the caller's output pipe (#207), and the reproducing test is kept in platform as an ignored test.
Every computed colour was painted on a 1x1 canvas and read back; Brave adds noise to canvas reads, so colours came back one unit off per channel (#F5F2EC as #f4f2ed). Computed rgb()/rgba() values are now read as numbers, and only other notations go through the canvas.
Fixes#154
Chrome reports Tailwind v4's rounded-full as its largest length, 3.35544e+07px; the capture now records any corner above 9999px as 9999px and keeps the other corners.
Fixes#155
A visitor's view of a site no longer keeps the page's class names (outline items and unnamed-control examples) or the query strings and fragments on image and link addresses, which can carry deployment ids and tokens.
Fixes#156
web_site_capture checks where the page is first and refuses, without making the output folder, when the browser is on its own error page or a blank one after a failed open. Fixes#158.
Before each width's full-page screenshot the page is scrolled through, lazy images are loaded and waited on (5 s at most), and it goes back to the top, so scroll-revealed sections and lazy images are in the picture. Fixes#160.
The engine test no longer connects to the stopped stand-in's port, which another parallel test could be handed; platform::standin_server tests that dropping a server frees its port, trying it for a moment.
When UI Automation's button or check box proxy fails (it uses SendInput, which needs an interactive desktop), the walkthrough posts BM_CLICK to the control's window instead. PostMessage, so a click that opens a dialog doesn't block the walkthrough; only for buttons and check boxes.
Taking over a replaced stand-in's port tries a busy port again for up to two seconds, so a restart no longer fails now and then with Address already in use.
runtime_captures_compare's right input had no description, so its schema was the boolean true and Claude Code rejected the whole tool list in Deep-mode builds. It gets a description, and a test checks every MCP input property schema is an object. Fixes#90.
engines_list, doctor, capabilities and Requires::Engine share Settings::engine_path, which honours the Ghidra folder setting, and locate() finds an engine unpacked into a versioned sub-folder.
Builders driven by our own loop (an API model such as Ollama) get file tools whose paths are
relative to the project. Models often write the project's folders from the root (/app/src/…), which
was refused as outside the project, so they could neither list, read nor write app/ and went round
in circles while each check found nothing. A path from the root whose first folder the project has
is now read inside the project (/etc/… and folders it doesn't have are still refused), and a write
outside app/ says so in its result, so a model that leaves out app/ learns where the app goes.
Refs #24
The status row names the command or file under way instead of only counting
actions. "More detail" opens the latest lines: stages, every command and file
with how it ended, what the builder said, and what programs printed outside the
conversation. Everything is kept in build-activity.log, with secrets hidden, and
the rebuild_activity_show tool and the CLI read the same.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Claude Code's figure is its own guess at API prices, which a subscription
isn't charged. The project page now says "AI cost (estimate)" with a note
saying so, and the title bar says "(estimate)". What an API key was charged
is kept apart in usage.json; older files count as estimates.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A run with no message was read as a first build, so Try again studied the
original again and gave the builder the first brief, even with its session
saved. A run now carries on when the builder has already worked, and only
runs the check when the builder had finished (awaiting_check in craft.json).
A check that returns an error couldn't look at the build at all, so it gets a
second go, and then the run says the build is finished but couldn't be checked.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Stop deadlocks as they form and watch every lock for one that never lets go
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Give the stuck-lock banner's test a program of its own
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Explain failed agent runs, keep a log to open, and stop offering git servers as computers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Fix a lock-up: the build's agent setup took the session lock twice in one statement
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A native, pure-Rust app that shows anyone how a piece of software works, with
evidence-backed answers, then helps them rebuild it. It ships a desktop app, a
CLI and an MCP server, all driven by one engine.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>