mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
M13.15: qa batch tool and reply affordances
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
12235b5dc5
commit
e2d7a5a182
2 files changed
+46
No files matched your search
@@ -0,0 +1,45 @@
|
||||
//! Agent affordances added during QA: the `batch` tool, ids and paths in replies, depth-limited
|
||||
//! flat property lists, `@uid` paths.
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
use crate::harness::Qa;
|
||||
|
||||
#[test]
|
||||
fn batch_tool_builds_in_one_call_and_one_undo_step() {
|
||||
let mut qa = Qa::new("batch");
|
||||
qa.exec("comp.new", json!({"name": "B", "width": 64, "height": 64}));
|
||||
let undo = qa.tool("get_project", json!({}))["undo"].as_array().unwrap().len();
|
||||
let r = qa.tool(
|
||||
"batch",
|
||||
json!({"label": "Ring", "steps": [
|
||||
{"command": "layer.newShape", "params": {"kind": "ellipse", "name": "Ring", "size": [40, 40]}},
|
||||
{"command": "layer.addShapeItem", "params": {"layer": "$1.layer", "kind": "trim"}},
|
||||
{"command": "prop.addKey", "params": {"layer": "$1.layer", "path": "transform/opacity", "time": 0, "value": 0}},
|
||||
{"command": "effect.apply", "params": {"layer": "$1.layer", "effect": "Glow"}},
|
||||
]}),
|
||||
);
|
||||
assert_eq!(r["steps"], 4);
|
||||
assert_eq!(r["results"][1]["path"], "contents/trim");
|
||||
assert_eq!(r["results"][3]["paths"], json!(["effects/#1"]));
|
||||
let p = qa.tool("get_project", json!({}));
|
||||
assert_eq!(p["undo"].as_array().unwrap().len(), undo + 1);
|
||||
assert_eq!(p["undo"].as_array().unwrap().last().unwrap(), "Ring");
|
||||
// A failing step: nothing changes, and the message names the step.
|
||||
let e = qa
|
||||
.try_tool(
|
||||
"batch",
|
||||
json!({"steps": [{"command": "layer.newNull", "params": {}}, {"command": "layer.rename", "params": {"layer": "Nope", "name": "x"}}]}),
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(e.starts_with("step 2 (layer.rename)") && e.contains("rolled back"), "{e}");
|
||||
assert_eq!(qa.tool("get_comp", json!({}))["layers"].as_array().unwrap().len(), 1);
|
||||
|
||||
// depth-limited flat listings keep cut-off groups visible; `@uid` reaches any property.
|
||||
let flat = qa.tool("get_layer", json!({"layer": "Ring", "flat": true, "depth": 1}));
|
||||
let props = flat["properties"].as_array().unwrap();
|
||||
assert!(props.iter().any(|p| p["path"] == "effects" && p["truncated"] == true), "{flat}");
|
||||
let uid = qa.tool("get_property", json!({"layer": "Ring", "path": "contents/trim/end"}))["uid"].as_u64().unwrap();
|
||||
let byuid = qa.tool("get_property", json!({"layer": "Ring", "path": format!("@{uid}")}));
|
||||
assert_eq!(byuid["name"], "End");
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
//! over JSON-RPC, the same commands the CLI and control channel run), asserting on rendered
|
||||
//! pixels and written files rather than on command success alone.
|
||||
|
||||
mod affordances;
|
||||
mod compositing;
|
||||
mod harness;
|
||||
mod kinetic;
|
||||
|
||||
Reference in new issue
Block a user