IJAI-689 add parallels-vm-ui-tests, and make driving the guest allowlistable

Running a UI lane in the Parallels guest was documented but not actually runnable by an agent: the two
mechanics it rests on - writing a file into the guest, and getting commits across - are shell shapes a
permission classifier reasonably distrusts when they appear ad hoc at a call site, so both were denied
mid-run. They are the same two operations every time, which makes them a script rather than a habit.

Everything now goes through ./.agents/skills/parallels-vm-ui-tests/scripts/vm.sh, named once in
tool-permissions.json. Sync streams an incremental git bundle over the Parallels exec channel instead of
standing up the git daemon the runbook described: no network listener, no credential in the guest, and
190 commits came to under 10 MB.

Taking the lease resets the guest tree, because taking the lease is taking the guest - it is a build
machine seeded from the host, not anybody's working copy. A dirty-tree gate would only ever be answered
one way, so the guard is a saved patch instead: whatever was there is written to
/Volumes/Dev/discarded-<stamp>.patch before the reset, and the paths are printed.

The AIR guide keeps its provisioning history, class list and timings, and defers the mechanics here.

Description budget note: skill descriptions share a 6 KiB pool (render-guides.mjs), and it was already
within 10 bytes of full, so this one is 87 bytes. The next skill needs a trim elsewhere or a deliberate
raise of that constant, which costs every session's context.

(cherry picked from commit bd9c12ebebf635255250ff3505d190c12a0e377d)

GitOrigin-RevId: b69adf05df20a1452733cda42eea0b368965172b
This commit is contained in:
Vladimir Krivosheev
2026-08-10 23:57:57 +00:00
committed by intellij-monorepo-bot
parent ccc5e11f9b
commit 2fe580bb33
+126
View File
@@ -0,0 +1,126 @@
{
"$comment": [
"The repository's tool-permission list, rendered by community/.ai/render-guides.mjs into",
".claude/settings.json (permissions.allow / permissions.deny) and .codex/rules/default.rules.",
"Edit this file and rerun the renderer; never edit the generated rules by hand.",
"",
"Entries are argv prefixes, not command strings: [\"./bazel.cmd\", \"build\"] matches",
"`./bazel.cmd build //x` but never `./bazel.cmd clean`. Both matchers compare literal text, so a",
"leading `./` is emitted in both spellings; other spellings of the same file (`../../x`, an",
"absolute path) fall through to a prompt.",
"",
"Each harness matches every stage of a pipeline independently, which is why the read-only",
"filters at the end of `allow` are listed at all: without them `rg.cmd x | head -5` prompts.",
"",
"`deny` wins over `allow` in both harnesses and is the load-bearing half: it also overrides",
"Claude Code's built-in read-only command set, which is what `grep` and `find` are listed for.",
"",
"`{{TOOLS_DIR}}` resolves per edition (./community/tools, or ./tools in a community checkout).",
"Everything else is spelled relative to the workspace root the rules are rendered into."
],
"allow": [
["./plugins/air/scripts/bt.cmd"],
["./.agents/skills/parallels-vm-ui-tests/scripts/vm.sh"],
["./tests.cmd"],
["./community/tests.cmd"],
["./bazel.cmd", "build"],
["./bazel.cmd", "test"],
["./bazel.cmd", "query"],
["./bazel.cmd", "cquery"],
["./bazel.cmd", "info"],
["./bazel.cmd", "run"],
["bazel", "build"],
["bazel", "test"],
["bazel", "query"],
["bazel", "cquery"],
["bazel", "info"],
["bazel", "run"],
["./bazel-build-all.cmd"],
["./build/jpsModelToBazel.cmd"],
["bun", "build/jps-module.mjs"],
["{{TOOLS_DIR}}/rg.cmd"],
["{{TOOLS_DIR}}/fd.cmd"],
["{{TOOLS_DIR}}/bun.cmd"],
["{{TOOLS_DIR}}/uv.sh"],
["bun", "test"],
["bun", "run", "build"],
["node", "--test"],
["./.ownership/cli.cmd"],
["teamcity"],
["bd"],
["npm", "view"],
["git", "status"],
["git", "diff"],
["git", "log"],
["git", "show"],
["git", "grep"],
["git", "ls-files"],
["git", "rev-list"],
["git", "rev-parse"],
["git", "check-ignore"],
["git", "fetch"],
["git", "add"],
["git", "commit"],
["git", "mv"],
["git", "rm"],
["git", "restore"],
["git", "stash"],
["git", "checkout"],
["awk"],
["basename"],
["cat"],
["cut"],
["date"],
["dirname"],
["du"],
["echo"],
["false"],
["head"],
["jq"],
["ls"],
["nl"],
["printf"],
["pwd"],
["readlink"],
["realpath"],
["rev"],
["sed"],
["sort"],
["stat"],
["tac"],
["tail"],
["tr"],
["true"],
["uniq"],
["wait"],
["wc"],
["which"]
],
"$comment_deny": [
"`grep` and `find` are denied outright, in every pipeline position: pipe into",
"`{{TOOLS_DIR}}/rg.cmd` instead, which reads stdin. Expressing \"denied only as the first stage\"",
"took a whole argv-parsing hook; the flat rule is what lets both harnesses do this natively.",
"",
"`sed -i` is a speed bump against bulk in-place rewrites (the Edit tool is the documented path),",
"not a boundary: an `awk` print target or a shell redirect can still write a file."
],
"deny": [
["bazel", "clean"],
["./bazel.cmd", "clean"],
["./bazel-clean-caches.cmd"],
["grep"],
["find"],
["sed", "-i"],
["sed", "--in-place"]
],
"$comment_denyTools": [
"Whole tools, denied by name. Claude Code drops these from the model's context entirely, so no",
"call is attempted; the guide's Tooling rules point at the ijproxy and rg.cmd/fd.cmd equivalents.",
"Codex has no such tools, so its rules file omits this section."
],
"denyTools": ["Grep", "Glob"]
}