automation: a proxy's relative name is a template, not a path (#2479)

Asked for on the PR: #1347 allows `file.createProxy` a name that is not a path,
because the engine reads it as an Output Module template, and the `WRITES` entry
added here refused exactly that. Dropped, so the classification is #1347's alone.

Nothing is opened by it. A proxy named outside the roots is still refused —
`cannot read` now rather than `cannot write`, which is #1347's to settle — so the
test asserts the refusal and no longer its wording. A relative name is now
accepted and resolves beside the saved project, inside the write root, which the
test pins so this does not quietly come back.

The lookup this PR is for is untouched: `file.createProxy` stays in
`QUEUES_AN_OUTPUT`, so a proxy queued from a project with no file is still
refused rather than landing in the home folder.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Anubhav-RaiandClaude Opus 5 committed 2026-10-29 10:09:15 +05:30
1 parent 80a33f0e86
commit 7df52fb20e
2 files changed
+6 -3

No files matched your search

-1
View File
@@ -86,7 +86,6 @@ const WRITES: &[(&str, &[&str])] = &[
("essential.exportTemplate", &["path"]),
("shortcuts.export", &["path"]),
("renderQueue.add", &["output", "path"]),
("file.createProxy", &["path", "output"]),
];
/// Commands that write where they are not told: the project's file, the Render Queue's outputs.
+6 -2
View File
@@ -1414,12 +1414,16 @@ fn automation_roots_refuse_a_queued_output_from_an_unsaved_project() {
assert_eq!(queue["items"].as_array().map(Vec::len), Some(0), "nothing was queued: {queue}");
// Naming an output inside a write root is how it is done.
call_json(&mut s, "execute_command", json!({"command": "renderQueue.add", "params": {"comp": "A", "output": p("named.mp4")}}));
// A proxy's own `path` is a write, not the read it used to be checked as (#2131 F-11).
// A proxy named outside the roots is refused. Whether that reads as a write or a read is
// #1347's to classify, so this asserts the refusal and not its wording.
let (c, err) = call(&mut s, "execute_command", json!({"command": "file.createProxy", "params": {"comp": "A", "path": "/elsewhere/proxy.mov"}}));
assert!(err, "a proxy outside the roots should be refused: {c:?}");
assert!(c[0]["text"].as_str().unwrap_or_default().contains("cannot write"), "{c:?}");
assert!(c[0]["text"].as_str().unwrap_or_default().contains("outside the automation roots"), "{c:?}");
// Once the project is saved there, the default output (beside it) is queued as before.
call_json(&mut s, "save_project", json!({"path": p("proj.ecproj")}));
// A name that is not a path is an Output Module template, and the output it resolves to lands
// beside the saved project: inside the write root, so it is allowed (#1347 relies on this).
call_json(&mut s, "execute_command", json!({"command": "file.createProxy", "params": {"comp": "A", "path": "ProxyTemplate"}}));
call_json(&mut s, "execute_command", json!({"command": "renderQueue.add", "params": {"comp": "A"}}));
let queue = call_json(&mut s, "execute_command", json!({"command": "renderQueue.list"}));
let out = queue["items"][1]["outputPath"].as_str().unwrap_or_default();