Skip to main content
Glama
NOTE

WeftCut is still under active development, so some features and UI/UX may change before v1.0.0. Join us to improve the project!

An agent editing the timeline live over MCP

Most editors bolt AI on as a feature: a button that generates something, a sidebar that suggests a cut. WeftCut exposes the editor itself as a tool surface. A localhost MCP server publishes all editing tools — place, trim, split, restyle, keyframe, group, caption, mix, checkpoint — and whatever agent you already have open drives them. The intelligence lives outside the app: the installer bundles no model weights, and the local engines for speech and vision are an opt-in download when you want them.

None of that rides on a stripped-down editor. Everything an agent can reach, you can do by hand, in a full NLE: A/B-roll timeline, keyframes with a curve editor, effects, captions, a role-based audio mixer, and hardware-accelerated export.

Quick start

NOTE

We don't have a verified macOS installer yet, so allow it under System Settings → Privacy & Security → Open Anyway

  1. Download the installer for your platform from the releases page.

  2. Install the app, open the settings panel, and copy the prompt that teaches your agent how to connect to WeftCut.

  3. Enjoy your work.

Related MCP server: opencut-mcp

Hand your timeline to an agent

Copy the prompt in settings into your client, and your agent is holding the editor.

  • It edits the project you are watching. No import/export round trip, no separate headless copy.

  • You can always see what it did. Every tool call becomes a row in the Agent panel — Trimmed clip · Ember.mp4, Added marker · Needs a look — and the status bar echoes it. Nothing happens off the record.

  • Every batch is reversible. Agents checkpoint at logical boundaries, and each checkpoint is one click from being restored. The agent can also rehearse a whole multi-step edit against a throwaway clone first (dry_run) and find the collision before it touches your project.

  • Multi-agent, with rules. Sessions are per-connection. An agent that is mid-batch can set_history_lock so a stray Ctrl-Z doesn't land in the middle of its work — and the lock, plus the reason it gave, is shown to you.

For a longer run, an agent can call begin_agent_session and fold the UI down to preview, scrub, and a record of what it is doing:

Agent mode — the activity panel while an agent works

Code as video: Motifs

A Motif is an on-screen element written as code — a real web page (HTML, CSS, SVG, canvas, WebGL, whatever you reach for) dropped on the timeline as a layer. It isn't a fixed preset: the author declares the knobs, and the inspector builds the form from that declaration, so seconds, label and accent below are editable in the app.

The one rule that makes it an editor feature instead of a screen recording: a Motif renders as a pure function of time. It never advances itself. The harness owns the clock and drives the page to each composition frame, so the same t always yields the same pixels — when you scrub, when you re-export, and in preview and export alike.

// The built-in Countdown's whole script, near enough verbatim — the rest of the
// file is the SVG ring it animates. `props` is whatever the manifest declares;
// `frame` runs once per composition frame and keeps no state of its own.
motif.define({
  setup: async function (props, ctx) {
    _label = props.label != null ? String(props.label) : "GO";
    num.style.color = props.accent;
    ring.style.stroke = props.accent;
    ring.setAttribute("stroke-dasharray", C);
    ring.animate([{ strokeDashoffset: 0 }, { strokeDashoffset: C }],
      { duration: ctx.duration * 1000, easing: "linear", fill: "both" });
  },
  frame: function (t, ctx) {
    var n = Math.max(0, Math.ceil(ctx.duration - t));
    num.textContent = n > 0 ? String(n) : _label;
  },
});

A Motif on the timeline, with its props in the inspector

Writing a web page is the thing coding agents are already best at — so an agent can author a brand-new overlay for your edit instead of picking one from a catalog. The authoring spec ships inside the app as an agent skill, so the model gets the contract without you pasting documentation.

Lower thirds, countdowns, karaoke text and animated title cards are the obvious uses. Anything you can build on a page is the actual limit.

A complete editor underneath

WeftCut editor

Timeline — A/B-roll rows with filmstrips and waveforms, frame-accurate SMPTE editing, ripple delete that closes the gap behind it, linked A/V that trims as one clip, cross-track groups, and nested compositions. Agent: move_layer · trim_layer · split_layer · ripple_delete_gap · create_link · create_group · move_layers_to_composition

Keyframes — animate any parameter, with bézier easing, a curve editor, tangent control, motion paths and extrapolation. Agent: set_keyframe · update_keyframe · smooth_keyframes · set_extrapolation

Speech and captions — transcribe a clip and get editable caption layers packed onto your caption tracks; import SRT/VTT/ASS into the media pool and drop it where it starts. Transcription runs against a cloud provider, or entirely on your machine once you let the app fetch a local engine (whisper.cpp, FunASR) — or an agent can pull the raw audio out and run its own model. Text-to-speech for scratch voiceover. Agent: transcribe_clip · extract_clip_audio · apply_transcripts · apply_subtitles · synthesize_speech

Audio — role-based mixing (dialogue / music / SFX / voiceover) with live per-role metering, gain, pan, fades and denoise. Pauses finds the dead air in a take and cuts it as one undoable edit, keeping a pad so speech still breathes. Agent: detect_pauses · remove_pauses · set_role_gain · set_role_flags

The Role Mixer console, metering during playback

Understanding the footage — shot-boundary detection with per-shot brightness, motion and sharpness, frame comparison, and vision-model descriptions of what a clip actually contains. An agent can cut on content, not just on timecode. Agent: analyze_clip · auto_split_by_shot · describe_clip · compare_frames

Titles, effects and transitions — styled text layers with outlines, per-layer effect chains including chroma key with an eyedropper that picks from the live frame, and transitions between clips. Agent: add_effect · update_effect · add_transition · update_transition

Export — H.264 / HEVC / AV1, hardware or software encoders, resolution / fps / quality controls, and streamed muxing.

Find anything — one Ctrl+K palette over commands, media, clips, captions and markers, search for whatever you want.

Search palette

Tech stack

Layer

Stack

Shell

Electron 44 · TypeScript 7 · electron-vite · Vite 8 · Node 24

UI

React 19 · Zustand · Immer · Tailwind CSS v4 · Base UI · shadcn/ui · Dockview · lucide · i18next (en-US / zh-CN) · fuzzysort

Preview

PixiJS v8 · WebGPU / WebGL · WebCodecs VideoDecoder pool · mediabunny · own YUV→RGB shaders · Web Audio clock

Export

Worker + OffscreenCanvas · GPU YUV pack pass · PBO readback · rawvideo over IPC · native ffmpeg sink · WebCodecs encoder (pin) · stream-copy mux

Native core

Rust · napi-rs 3 · Tokio · imbl · serde · schemars · blake3 · reqwest · ffmpeg-sidecar

Native decode

@weftcut/native-decode · ffmpeg-next · software + GPU lanes · sharedTexture (Windows)

Shared math

weftcut-eval crate · native + wasm32 · snap · keyframe eval · envelope · role gate

ffmpeg

GPL CLI sidecar (jobs, encode, mux) · LGPL shared libs (in-process decode)

Agent surface

MCP · streamable HTTP on localhost · @modelcontextprotocol/sdk · bearer token · TS + Rust tool catalog

Motifs

Offscreen BrowserWindow · Chrome DevTools Protocol · motif: scheme · CSP default-src 'none'

Speech & vision

Cloud providers over reqwest · whisper.cpp · FunASR · on-demand model download

Tests & CI

Vitest · cargo test · Playwright · node --test · Stryker · GitHub Actions (Windows / macOS / Linux)

Design decisions: ADRs.

Build from source

Prerequisites: Node 24+, Rust (stable via rustup), and your platform's C++ build tools — per-OS commands in docs/setup.md.

npm install       # JS dependencies
npm run bootstrap # one-time: fetch ffmpeg + build the Rust addons
npm run dev       # start the editor

Also useful: npm run typecheck, npm test, npm run e2e, npm run build, npm run package (installers).

Documentation

Start with architecture for the system map, or MCP server & agent UX for the tool surface, resources and multi-agent behavior. Motifs and motif authoring cover the overlay engine and its contract.

  • Data model — project state schema, history, persistence, validation.

  • Render — PixiJS + WebCodecs renderer architecture.

  • Preview — interactive preview surface and transport.

  • Export — export settings and range, audio export, final mux, proxies, background jobs.

  • Captions · Audio — caption ingestion and the audio engine.

  • Conformance — media fixtures and E2E gates for frame alignment, audio sync, colour.

  • Features — small-feature contracts: undo-stack scope, groups, search palette, colour picker.

  • Status / log system — the bottom-of-editor log bus.

  • Setup — per-OS toolchain prerequisites and first-run flow.

  • Licensing — MIT app plus the two FFmpeg lanes and their build-time compliance gates.

  • v1 target — release scope and open work, tracked as an issue: docs/ describes what exists today.

Community

Join the WeftCut Discord community to share feedback, discuss feature ideas, and get help. Please use GitHub Issues for bug reports and feature requests so they can be tracked.

Maintainer

WeftCut is built and maintained by UncleChair.

It exists to speed up my own video work. I wanted an editor an agent could actually drive, and a timeline I could keep watching while it did — so the MCP surface is the part I use daily, not a demo bolted onto the side. Motifs came from the other half of that: the overlays I wanted were easier to write than to find, and an agent that can write a web page can write one for the shot in front of it.

The project sits under the WeftCut organization so the name, domain and releases have a stable home, but it is a one-person project — issues and pull requests all reach me.

Star History

License

WeftCut is licensed under the MIT License. Packaged installers bundle FFmpeg binaries under their own licenses (LGPL shared libraries for in-process decode, GPL command-line tools run as a separate process) — see THIRD-PARTY-NOTICES.md and docs/licensing.md for the full model.

Available Tools

103 tools
add_audio_layerA

Add an Audio layer from an imported item onto a track's audio lane and return its record — music, a sound effect, a voice track, or a video file's audio on its own. The only way audio-only media reaches the timeline (add_video_layer refuses it). media_id is an Audio item or a Video item with an audio stream; Image and Subtitle are refused. The layer stands ALONE — no auto-pair, no link — on the track's audio lane (every track has one, beside its visual lane). src_in_us/src_out_us are source in/out, t_start_us/t_end_us the timeline span; both snap to the 48 kHz sample lattice. role (default music) picks the mixing bus — a property of the clip, not its track.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleNoMixing bus for the clip. Defaults to `music`.
media_idYesMedia id.
t_end_usYesTimeline end (exclusive), µs.
track_idYesTrack id.
src_in_usYesSource in point, µs.
src_out_usYesSource out point (exclusive), µs.
t_start_usYesTimeline start, µs.
composition_idNoOptional composition check for track_id; mismatch rejects. track_id fixes the composition.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint:false in annotations, the description carries the real burden and delivers: the layer stands ALONE with no auto-pair and no link, it lands on the track's audio lane, timing snaps to the 48 kHz sample lattice, and role is a clip property rather than a track property. This is exactly the behavioral context annotations cannot provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the key differentiator are front-loaded in the first sentence, and the remaining sentences each add distinct value (media constraints, standalone behavior, timing, role). It is dense and slightly long, but there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation tool with no output schema, the description covers purpose, media eligibility, lane behavior, timing semantics, and the role default, and states that it returns the layer's record. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning beyond the schema: src_* are source in/out versus t_* the timeline span, both snap to the 48 kHz sample lattice, and role selects the mixing bus (a clip property). That clarifies the semantics of overlapping-looking fields the schema labels tersely.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (add an Audio layer onto a track's audio lane), names the return value, and explicitly distinguishes itself from the sibling add_video_layer ('the only way audio-only media reaches the timeline'). An agent can select it correctly without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit routing condition versus the alternative: use this for audio-only media because add_video_layer refuses it. It also states which media types are accepted (Audio item or Video item with audio stream) and which are refused (Image, Subtitle), leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_color_layerA

Add a solid-color layer to a track and return its record — layer_id, track_id, the span as committed, adjusted for any grid snap. t_start_us and t_end_us are timeline microseconds (start inclusive, end exclusive). Layer cannot overlap existing layers on the same track.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorYesFill colour.
widthNoBlock width, px; default 1920.
heightNoBlock height, px; default 1080.
t_end_usYesTimeline end (exclusive), µs.
track_idYesTrack id.
t_start_usYesTimeline start, µs.
composition_idNoOptional composition check for track_id; mismatch rejects. track_id fixes the composition.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false in annotations, the description carries most of the burden and delivers: it discloses the return fields (layer_id, track_id, committed span, adjusted flag), warns that grid snap may alter the requested span, and states the non-overlap rule for the same track. It does not cover permissions or failure behavior on overlap, but it adds real behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the action and return contract, followed by unit semantics and the key constraint. No filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-param tool with no output schema, the description usefully explains what the call returns and the one hard constraint. Remaining gaps (error behavior on overlap, whether snapping can be disabled, required permissions) are minor but real.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description clarifies the µs unit and the inclusive/exclusive boundary semantics, which largely restate what the schema already documents, and adds the 'adjusted for grid snap' meaning for the committed span. No new meaning is added for color, width, height, or composition_id.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Add a solid-color layer to a track') and distinguishes itself from the many sibling add_*_layer tools by naming the exact layer type. The second clause clarifies the return behavior, so an agent knows both the action and the response shape.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the tool's specialized purpose (color layer vs video/audio/text/group layers), and the non-overlap constraint tells the agent a precondition. However, it never explicitly says when to choose this over add_video_layer/add_text_layer, nor what happens if the precondition fails.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_effectA

Append an effect to a layer's chain (applied last) and return its record (effect_id, kind, index). kind is the catalog key. Visual kinds ("blur", "chromakey", "brightness", "contrast", "saturation", "sharpen") go on visual layers: the colour trio take amount in [-100, 100] (percent offset, 0 = no change), "sharpen" takes amount in [0, 100]. Audio kinds are the audio.* namespace, for Audio layers ONLY, and their params are STATIC ONLY (set_keyframe on one is AudioEffectParamStatic); a kind on the wrong layer kind is EffectKindNotApplicable. The one audio kind is "audio.denoise": strength dB [1, 40] (default 12), margin dB [0, 20] (default 8), and profile_in_us/profile_out_us, SOURCE-time bounds of a noise-only span ≥ 250000 µs — it does nothing until both are set. The effect is created with no params: set a static value with update_effect first, then (visual only) set_keyframe on effects[<id>].params[<key>]. effects://catalog (or read_project { view: "effects" }) lists every kind's params, defaults and ranges.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYesCatalog key: visual kinds on visual layers, audio.* on Audio layers.
layer_idYesLayer id.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description carries the behavioral burden. It adds significant context: the effect is created with no params, audio params are static-only, audio.denoise does nothing until both profile bounds are set, and wrong layer kinds yield EffectKindNotApplicable. It also discloses the return record shape. This goes far beyond the structured annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but dense and purposeful: every clause adds operational detail—return shape, visual/audio rules, ranges, defaults, worklow, and catalog pointer. It is front-loaded with the core purpose and then organizes constraints and usage in a logical sequence. No filler sentences are present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given two required parameters, no output schema, and only a minimal annotation, the description is fully complete: it covers the return record, all kind-specific parameters, defaults, error behavior, and the required sequencing after creation. An agent has everything it needs to call add_effect correctly without external lookup.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description dramatically expands the meaning of `kind`: catalog semantics, visual vs. audio layer compatibility, parameter ranges and defaults, and static-only restrictions. `layer_id` is simple enough that no further explanation is needed. This is a model of adding value beyond the input schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb, resource, and ordering: 'Append an effect to a layer's chain (applied last) and return its record (`effect_id`, `kind`, `index`).' This clearly distinguishes add_effect from siblings like update_effect, move_effect, and delete_effect by defining exactly what this tool does and what it returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives strong usage context: visual kinds go on visual layers, audio.* kinds are for Audio layers only, and a kind on the wrong layer fails with EffectKindNotApplicable. It also spells out the post-creation workflow (set static value via update_effect, then optionally set_keyframe for visual params). It does not explicitly contrast with move_effect/update_effect, but the guidance is sufficient for an agent to know when to use this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_group_layerA

Place an EXISTING composition on a track as one more Group layer (create_group makes a NEW one). source_composition_id is what gets placed (ids and reference counts: project://compositions); track_id and t_start_us are where. The layer is windowed over the whole composition (src_in_us: 0, src_out_us: duration_us) with an identity transform; trim it afterwards for a slice. Instances are independent and all show the same content. Refuses before creating anything: the root (RootComposition), a composition that already reaches this track's composition, itself included (CompositionCycle), and an empty composition (InvalidArgument).

ParametersJSON Schema
NameRequiredDescriptionDefault
track_idYesTrack id.
t_start_usYesTimeline start, µs.
composition_idNoOptional composition check for track_id; mismatch rejects. track_id fixes the composition.
source_composition_idYesThe composition to place — a Group's id from `project://compositions`, never the root.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only `destructiveHint: false` in annotations, the description carries the burden well: it discloses default windowing (`src_in_us: 0`, `src_out_us: duration_us`), identity transform, independent instances sharing content, and the precise refusal cases with error names (RootComposition, CompositionCycle, InvalidArgument) guaranteed before any mutation. This is rich behavior beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the create_group contrast, and every sentence adds information (semantics, defaults, refusal cases). It is dense with parentheticals and could be marginally tighter, but there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers placement semantics, defaults, and failure modes thoroughly. The only minor gap is that it never hints at what a successful call yields (e.g. a new layer id for follow-up operations), which an agent might want.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: `source_composition_id` is the placed content, `track_id`/`t_start_us` are the location, and it notes the whole-composition windowing default. It does not discuss the optional `composition_id` check parameter, which the schema handles instead.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (place an EXISTING composition as a Group layer) and explicitly distinguishes itself from the sibling `create_group` ('makes a NEW one'). An agent can tell exactly what this does and how it differs from the create path.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative (`create_group`) and the condition separating them (existing vs new composition), and gives follow-up guidance ('trim it afterwards for a slice'). It also points to `project://compositions` for valid ids, so the agent knows when and how to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_group_membersA

Move selected clips into an existing Group while preserving external placement. Requires Group rate 1 and compatible selection. Refuses partial links, locked members and cycles. Returns the resulting Group.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idsYesThe layers to move in; at least one, all in one composition.
group_layer_idYesThe Group clip they move into — a `CompositionRef` layer in the SAME composition as the members.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false in the annotations, the description carries the disclosure burden and does so well: it names the refusal conditions (partial links, locked members, cycles) and the return value. It could say more about what 'preserving external placement' actually guarantees, but the failure-mode disclosure is strong context beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences: action, preconditions/refusals, return. Zero filler and the core action is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, 'Returns the resulting Group' is necessary and present, and refusal conditions are covered. Minor gap: no mention of atomicity/partial-failure behavior for a multi-layer move, but the description is otherwise complete for a 2-param tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both layer_ids and group_layer_id are already documented as same-composition and singular/multiple respectively. The description adds no syntax or format detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource+scope: move clips into an *existing* Group, which implicitly distinguishes it from create_group and add_group_layer in the sibling list. An agent can tell what this does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives prerequisites (Group rate 1, compatible selection) but never states when to choose this over create_group, add_group_layer, or ungroup_layer. Usage is implied by the preconditions rather than routed against alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_markerA

Add a marker (point or region) to a composition's timeline — the root, or the Group named by composition_id. Returns the marker record (marker_id, t_us as snapped). Set end_t_us to make it a region marker. Set anchor_layer_id to have the mark FOLLOW a clip instead of standing at a fixed time; omit it for an ordinary marker.

ParametersJSON Schema
NameRequiredDescriptionDefault
t_usYesMarker time, timeline, µs.
colorYesMarker colour.
labelYesShort name shown on the marker lane.
end_t_usNoRegion end, timeline; omit for a point marker, µs.
composition_idNoComposition to create in — a Group's id from `project://compositions`; omit for the root.
anchor_layer_idNoClip the marker should follow — a layer of the same composition with a source window (VideoClip, Audio, Group). Tied as `set_marker_anchor` would tie it, refused for the same reasons (no marker is created). Omit for a fixed marker.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false in annotations, the description carries the burden and delivers: it discloses the return value ('Returns the marker record (marker_id, t_us as snapped)'), reveals time-snapping behavior, and states the failure mode for an invalid anchor ('refused for the same reasons (no marker is created)'). None of this is available from annotations, and it does not contradict destructiveHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero filler. The first sentence front-loads the core action, target, and return value; the second and third each add exactly one variant dimension (region vs point, anchored vs fixed). Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a 6-parameter creation tool with no output schema: the description covers the return record shape (since there is no output schema), the key decision axis of root vs named composition, and both optional-behavior switches. Required params (color, label, t_us) are fully documented in the schema, and annotations cover the safety profile.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: it reveals that t_us is returned 'as snapped' (behavioral semantics the schema doesn't capture), and it frames end_t_us and anchor_layer_id as mutually exclusive marker-type selectors. The schema itself is already rich for anchor_layer_id, so the description complements rather than repeats.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Add'), resource ('marker'), and target ('composition's timeline — the root, or the Group named by composition_id'). It distinguishes point vs region markers and anchored vs fixed markers, which separates it from sibling tools like set_marker_anchor, update_marker, and delete_marker without needing to open their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear selection context for the two major variants: set end_t_us for a region marker, set anchor_layer_id to follow a clip vs omit for an ordinary marker. It references set_marker_anchor as the analogous tie operation, implicitly distinguishing creation-time anchoring from post-hoc anchoring. However, it never explicitly says 'use update_marker to modify an existing marker' or 'use delete_marker to remove one' — those exclusions are left to inference from sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_motif_layerA

Add a Motif layer and return its record. Read list_motifs for motif_id and props_schema. Omitted track_id creates a fresh track; omitted props use defaults. Unknown props reject.

ParametersJSON Schema
NameRequiredDescriptionDefault
propsNoMotif props as a JSON object. Keys must match the motif's `props_schema`; unknown keys reject; missing keys fill from defaults. Omit entirely to use all defaults.
motif_idYesMotif id from `list_motifs` (built-ins: "countdown", "lower-third", "text-fx").
t_end_usNoLayer end in timeline microseconds. Defaults to `t_start_us + default_duration_s * 1_000_000` when omitted.
track_idNoTarget track id. If omitted, a fresh track is spawned; it carries no stored name and is displayed by its position.
t_start_usYesLayer start in timeline microseconds.
composition_idNoThe composition the spawned track opens in (a Group's id); omit for the root. With `track_id` set, the track must belong to it.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false in annotations, the description carries real behavioral weight: it discloses that omitting track_id spawns a fresh track (a side effect), that omitted props fall back to defaults, and that unknown props are rejected (error behavior). It does not address undoability or permission requirements, so it is strong but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences with the core action front-loaded and no filler; each clause conveys a distinct fact (discovery, defaults, error behavior). Slightly dense but well structured and appropriately sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter tool with a nested props object and no output schema, the description covers the prerequisite (list_motifs), default behavior, and rejection rules. It mentions returning a record but doesn't characterize that record, a minor gap given no output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter in detail, including the same 'omit to use defaults' and 'unknown keys reject' notes. The description largely restates those facts rather than adding new parameter meaning, which is the baseline 3 for a fully documented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Add a Motif layer') and states it returns the new record, so the core action is unambiguous. It does not, however, explicitly distinguish this tool from the many sibling layer-creators (add_text_layer, add_video_layer, add_audio_layer, add_group_layer), relying on 'Motif' alone to carry the distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It supplies a real prerequisite ('Read list_motifs for motif_id and props_schema'), which steers the agent to the discovery step before calling. There is no explicit when-to-use vs. when-not guidance and no named alternative among the sibling layer-add tools, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_text_layerA

Add a Text layer — a title, a lower third, a credit — and return its record. Born at the app default text font (bundled caption font when unset), 72 px, opaque white, centre-aligned and centred in frame. x/y (both or neither) override placement and are the layer's ANCHOR point, not clamped to frame. Everything else — font, size, colour, outline, layout box, alignment — is update_layer_params { kind: 'Text' }. It cannot overlap another visual layer on the track. Subtitles from a document are apply_subtitles; this is the one-off.

ParametersJSON Schema
NameRequiredDescriptionDefault
xNoAnchor x in composition pixels. Give it with `y` or not at all; omitted, the layer is centred in frame.
yNoAnchor y in composition pixels. Give it with `x` or not at all.
contentYesThe text to display. Newlines are honoured.
t_end_usYesTimeline end (exclusive), µs.
track_idYesTrack id.
t_start_usYesTimeline start, µs.
composition_idNoOptional composition check for track_id; mismatch rejects. track_id fixes the composition.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description carries most of the burden and does well: it discloses the born-at defaults (font, 72 px, opaque white, centred), that x/y are an anchor not clamped to frame, and the hard constraint that the layer cannot overlap another visual layer on the track. It stops short of permissions or failure/auth behavior, keeping it out of the top band.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then defaults, then placement semantics, then the overlap rule, then the alternative sibling. Dense but every clause carries distinct information; the em-dash catalogue is stylistically heavy but not wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a create tool with a thin annotation set and no output schema, the description covers defaults, placement anchor rules, the styling hand-off, the overlap constraint, and the sibling alternative. Nothing essential for a correct call is missing; only edge-case failure behavior is unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3 and the schema already documents each field. The description still adds real meaning beyond it: x/y must be given "both or neither," and they define the ANCHOR point, unclamped to the frame — semantics the schema only partially implies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Add a Text layer") with concrete examples (title, lower third, credit) and promises the returned record. It explicitly distinguishes itself from `apply_subtitles` (one-off vs. document-derived) and implicitly from `add_video_layer`/`add_color_layer`, so an agent can select it without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative route explicitly — subtitles from a document go to `apply_subtitles`, "this is the one-off" — and points to `update_layer_params { kind: 'Text' }` for all further styling. When-to-use and when-not are both stated with no inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_trackA

Add a track and return its record (track_id, index, composition_id). Tracks are kind-agnostic — any layer kind goes on any track. A track disappears when its last layer leaves it (deleted or moved away), so place a layer rather than reserving a track; a track created empty survives until it has been filled and emptied.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelNoOptional name. Omit it and the track is displayed by its position in the stack, which renumbers as tracks come and go.
composition_idNoComposition to create in — a Group's id from `project://compositions`; omit for the root.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the single destructiveHint annotation, disclosing that tracks are kind-agnostic, auto-disappear when their last layer leaves, and that empty tracks survive until filled and emptied. This is valuable side-effect information an agent needs to predict tool behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler: the first states the action and return value, the second explains the critical lifecycle behavior. The most decision-relevant information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description names the exact return fields, making the response shape predictable. Combined with the 100% schema coverage for parameters and the lifecycle disclosure, nothing essential is missing for an agent to invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both parameters clearly. The description adds no parameter-specific meaning beyond the schema, but it does reinforce the optionality of label and composition_id through the lifecycle context. This matches the baseline for full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Add a track and return its record,' clearly identifying the operation and its result. It also differentiates this tool from siblings like delete_track, rename_track, and move_track by focusing on creation and the returned fields.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear behavioral guidance: tracks are not meant to be reserved, so users should place a layer rather than create an empty track for later use. It does not explicitly name alternative tools, but the lifecycle explanation effectively tells the agent when creation is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_transitionA

Add a transition at the cut between two adjacent layers on the same track — from_layer_id (outgoing) ends exactly where to_layer_id (incoming) starts — and return its record. kind 'Crossfade' (default) | 'Wipe' | 'Slide'; direction is the MOTION direction ('left' = the boundary or the sliding content moves left), required for Wipe/Slide and rejected for Crossfade. placement 'overlap' (default) moves the INCOMING layer left by the frame-rounded duration so both still play exactly their trimmed ranges and the vacated span stays a gap — nothing ripples; link siblings follow, bouncing to a free lane. 'extend' instead borrows outgoing tail media past its out-point, positions untouched (extended_us = duration), refused with TransitionInsufficientHandle { available_us } when the tail is short. A pair already overlapped by exactly the duration attaches as-is. Refuses: participants sharing a link, a move crossing t = 0, a duration longer than either participant, an Audio participant (TransitionUnsupportedLayerKind). Recorded — one undo restores every moved layer.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoDefault Crossfade.
directionNoMotion direction. Required for Wipe / Slide, refused for Crossfade.
placementNo'overlap' (default): the incoming layer moves left, trimmed ranges preserved. 'extend': the outgoing layer borrows tail media, positions untouched.
duration_usYesTransition length, µs.
to_layer_idYesIncoming layer — the one that starts at the cut.
from_layer_idYesOutgoing layer — the one that ends at the cut.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide destructiveHint=false, but the description discloses substantial side effects: overlap moves the incoming layer left, link siblings follow, nothing ripples, extend borrows media, and one undo restores every moved layer. It also documents error codes like TransitionInsufficientHandle and TransitionUnsupportedLayerKind.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but dense, with every clause contributing operational value. It is front-loaded with purpose, then parameter semantics, then refusals, and contains no filler or redundant restatement of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers prerequisites, side effects, placement behavior, refusal conditions, and error types. The only notable gap is that, with no output schema, it mentions returning 'its record' but does not specify the record's shape or fields; for a tool this complex, that is a minor omission.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description adds meaning well beyond the enum strings: direction is explained as MOTION direction with concrete left/right behavior, placement distinguishes movement vs. media borrowing, and from/to layer roles are defined. This materially helps an agent choose correct parameter values.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: adding a transition at the cut between two adjacent layers on the same track, with from/to roles and a returned record. It clearly distinguishes from sibling tools like update_transition and delete_transition by focusing on creation and placement semantics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when the tool is valid: prerequisites, placement modes, and refusal conditions. However, it does not explicitly name alternatives such as update_transition or delete_transition for cases where the agent should edit or remove an existing transition instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_video_layerA

Add a visual layer from an imported Video or Image item onto a track and return its record; an audio-only item is refused and pointed at add_audio_layer. Video: src_in_us/src_out_us are the source in/out points, t_start_us/t_end_us the timeline span. Image: an ImageOverlay over the timeline range; omit src_in_us/src_out_us. When a Video has an audio stream and auto_pair_audio_on_import is on (the default), a linked dialogue Audio layer lands on the SAME track's audio lane, committed atomically — an occupied lane rejects the whole call naming the blocker. The record always carries audio_layer_id/link_id/audio (null when unpaired).

ParametersJSON Schema
NameRequiredDescriptionDefault
media_idYesMedia id.
t_end_usYesTimeline end (exclusive), µs.
track_idYesTrack id.
src_in_usNoSource in point, µs. Required for Video; ignored for an Image.
src_out_usNoSource out point (exclusive), µs. Required for Video; ignored for an Image.
t_start_usYesTimeline start, µs.
composition_idNoOptional composition check for track_id; mismatch rejects. track_id fixes the composition.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description carries the real behavioral burden and does so richly: atomic commit of an auto-paired dialogue Audio layer onto the same track's audio lane, the default state of `auto_pair_audio_on_import`, and the failure mode ('an occupied lane rejects the whole call naming the blocker'). This is exactly the kind of context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Information-dense and front-loaded with the core action, then type-specific parameter rules, then the pairing/atomicity caveat. Every clause carries weight, though the long single paragraph and heavy backtick density make it slightly harder to scan than ideal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description explicitly documents the returned record's fields (`audio_layer_id`/`link_id`/`audio`, null when unpaired), plus the atomicity and error semantics. A 7-parameter mutation tool is fully covered with nothing an agent needs to call it correctly left out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so baseline is 3, but the description adds interpretable meaning: src_in_us/src_out_us are 'source in/out points' vs t_start_us/t_end_us as 'the timeline span', plus the Image-omit rule. It stops short of documenting media_id/track_id/composition_id beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Add a visual layer from an imported Video or Image item onto a track and return its record') and explicitly distinguishes itself from siblings, naming `add_audio_layer` as the destination for audio-only items. An agent can tell it apart from add_color_layer/add_text_layer/add_audio_layer without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (visual content from Video/Image) and when-not-use ('an audio-only item is refused and pointed at `add_audio_layer`'). It also differentiates the two accepted item types by parameter behavior (Video requires src_in/src_out; Image omits them).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

analyze_audioA
Read-only

Analyze original source audio from cached waveform peaks; local, read-only, no model. Returns source-absolute microseconds, bounded peak/RMS waveform bins, onset candidates and signed energy changes (dB), plus resolution and event counts. Choose music edit/alignment points, including outside a clip's trim. These are amplitude measurements, not beats, bars or melody recognition. At most 60 s per call; max_points affects only the summary. Peaks are cache-limited, not true-peak or LUFS. Wait for the waveform job if not ready. To place a source event at timeline T: src_in_us = source_us - (T - layer.t_start_us).

ParametersJSON Schema
NameRequiredDescriptionDefault
end_usNoSource-absolute end, exclusive. Default start + 60 seconds, capped at media end. At most 60 seconds per call.
media_idYesImported Audio or Video media id; analyzes its original audio before mix/effects.
start_usNoSource-absolute start in microseconds, inclusive. Default 0.
max_pointsNoMaximum waveform summary bins, 1..1000 (default 200). Does not change event detection resolution.
onset_threshold_dbNoMinimum short-time energy rise for onset candidates, 1..30 dB (default 6). Candidates are not beats or melody labels.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description adds substantial beyond-annotation context: the 60 s per-call cap, cache-limited peaks (not true-peak or LUFS), max_points affecting only the summary, and the explicit caveat that these are amplitude measurements rather than beats/bars/melody. That is exactly the behavioral disclosure a caller needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: what it does, what it returns, then scope and limits. Almost every sentence earns its place, though the description is longer than strictly necessary and packs several distinct caveats together.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description must describe return values, and it does so concretely (microseconds, bins, onsets, dB, resolution, counts). Combined with the caveats and the source-to-timeline formula, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description reinforces source-absolute microseconds and that max_points affects only the summary, but the schema already carries these meanings, so it adds little beyond structured data; the timeline-placement formula is usage guidance rather than parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (analyze original source audio from cached waveform peaks) and immediately scopes it as local, read-only, no model. It enumerates the return payload (source-absolute microseconds, peak/RMS bins, onsets, signed dB changes, resolution, event counts), which distinguishes it clearly from siblings like analyze_clip or extract_clip_audio.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use context: 'Choose music edit/alignment points, including outside a clip's trim', plus the operational prerequisite 'Wait for the waveform job if not ready.' It does not name an alternative tool or state when-not to use it, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

analyze_clipA
Read-only

Detect shot boundaries in a VideoClip layer. Deterministic, over the source (720p proxy preferred). Returns { shots: [{ index, t_start_us, t_end_us, keyframe_t_us, brightness, motion, sharpness, flags }], cut_scores: [{ t_us, score }] }, all SOURCE-ABSOLUTE µs clipped to the layer's source window. shots is the cleaned segmentation (cuts closer than min_shot_us merged), cut_scores the raw cut signal (0..1). Per shot: keyframe_t_us is the midpoint cover frame; brightness mean luma 0..1; sharpness variance of the Laplacian (higher = sharper); motion 0..1 endpoint difference; flags may hold "black", "freeze", "fade". Optional sensitivity (0..1, default 0.4; lower = more cuts), min_shot_us (default 500000), passes (subset of "shots" / "stats" / "events", default all — drop "stats" / "events" for timing only). VideoClip layers only. To split at every cut in one edit use auto_split_by_shot.

ParametersJSON Schema
NameRequiredDescriptionDefault
passesNoWhich passes to run — a subset of `["shots", "stats", "events"]`. Default all. Drop `"stats"` / `"events"` to skip per-shot frame sampling and return timing only.
layer_idYesTarget VideoClip layer id.
min_shot_usNoMinimum shot duration (microseconds); cuts closer than this are merged. Default 500000 (0.5 seconds).
sensitivityNoCut sensitivity in [0.0, 1.0]: a frame whose shot-change score exceeds this starts a new shot. Lower = more (finer) cuts. Default 0.4.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnlyHint=true, so the description correctly aligns with that. It adds substantial behavioral detail beyond annotations: deterministic operation, source-absolute timestamps clipped to the layer's window, the merging behavior for min_shot_us, and the structure of the returned shot and cut_scores. This gives agents a full picture of what happens during execution and what to expect from the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence earns its place. It front-loads the core purpose, then the return structure, then parameter explanations, then usage alternatives. There is no redundancy or filler—each detail directly aids correct invocation. The structure is logical and scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (4 parameters, detailed output, and no output schema), the description is fully self-sufficient. It explains the output format, parameter semantics, default values, usage constraints, and alternative tools. There is nothing an agent needs to know to call it correctly that is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though schema coverage is 100%, the description adds meaning beyond the schema. It explains the effect of sensitivity ('lower = more cuts'), the default for min_shot_us (500000), and the purpose of passes (dropping 'stats'/'events' for timing only). These clarifications help agents choose correct values and interpret the behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a precise action: 'Detect shot boundaries in a VideoClip layer.' It names the resource (VideoClip layer) and the output (shot boundaries) clearly. It also explicitly differentiates from the sibling auto_split_by_shot by noting the alternative for splitting, so an agent can distinguish it from other analysis tools like detect_pauses or compare_frames.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit guidance: 'VideoClip layers only' restricts scope, and it names the alternative tool for splitting with 'To split at every cut in one edit use auto_split_by_shot.' It also gives a usage tip about the 720p proxy preference, helping agents choose the right input. This is clear when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

apply_subtitlesA

Lay an imported Subtitle item (a .srt/.vtt/.ass from import_media) onto the caption tracks as one editable Text layer per cue, one recorded edit. The whole document lands, its time 0 at t_start_us. Each cue packs onto the first unlocked caption track with room, opening a new one only where it collides with all of them. Advanced ASS styling is simplified. Returns { caption_track_id, cues, simplified }.

ParametersJSON Schema
NameRequiredDescriptionDefault
media_idYesSubtitle media id.
t_start_usNoWhere the document's time 0 lands on the timeline; default 0, µs.
composition_idNoComposition to create in — a Group's id from `project://compositions`; omit for the root.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply `destructiveHint: false`, so the description carries the real burden and delivers: it discloses the packing algorithm (first unlocked track with room, new track only on collision), the single-undo-edit granularity, the ASS-styling simplification caveat, and the return shape including a `simplified` flag. This is the kind of behavior an agent cannot infer from structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Densely packed into three sentences with the core action front-loaded and every clause carrying information (track packing, undo granularity, styling caveat, return value). The time-0 restatement slightly echoes the schema, so it is not perfectly waste-free, but there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating, multi-part operation with no output schema, the description covers prerequisite, placement semantics, track-selection behavior, styling limitations, and the return payload. Nothing an agent needs in order to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters. The description restates `t_start_us` as the document's time 0 and `composition_id` as root-when-omitted, which largely duplicates the schema text rather than adding syntax or edge-case meaning. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (lay onto caption tracks) and resource (an imported Subtitle item's cues as editable Text layers), and distinguishes itself from the import step by naming `import_media` as the source and `Subtitle` as the artifact. An agent can tell it apart from `apply_transcripts` or `restyle_captions` from the description alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It establishes the prerequisite clearly — the item must already be imported via `import_media`. It gives context for placement via `t_start_us` and `composition_id`, but never states when NOT to use it or which sibling (e.g. `apply_transcripts`, `restyle_captions`) handles a related job. Clear context, no explicit alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

apply_transcriptsA

Lay transcripts on the caption tracks, KEEPING per-word timing; returns { caption_track_id, cues }. Pass transcribe_clip's envelope as it comes (segments and word_timing), or your own cues with word_timing: 'none'; correct_caption_text needs word offsets to re-segment a corrected cue. Cues pack into the composition's existing caption tracks, opening a lane only for a cue that collides with all of them, and snap to the frame grid. source_layer_ids is parallel to transcripts and tags each cue with the clip it came from, so corrections group by take. At most 1000 transcripts. One recorded edit.

ParametersJSON Schema
NameRequiredDescriptionDefault
transcriptsYesOne entry per transcribed clip, in the shape `transcribe_clip` returns.
composition_idNoComposition to create in — a Group's id from `project://compositions`; omit for the root.
source_layer_idsNoParallel to `transcripts`: the layer each was transcribed from.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only a non-destructive annotation, the description carries the behavioral load well: cues pack into existing tracks, a lane opens only on total collision, cues snap to the frame grid, `source_layer_ids` tags cues by take, a 1000-transcript cap, and 'One recorded edit' discloses undo semantics. Rich context beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded, opening with the core action and return value before the input-shape guidance. Every sentence carries information, though the paragraph is packed and could be slightly more scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema is needed — the description already names the returned fields. For a three-parameter layout tool, it covers inputs, packing behavior, limits, and undo, leaving nothing an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: `source_layer_ids` is parallel to `transcripts` and tags each cue with its source clip so corrections group by take. The `word_timing` enum is also explained in prose (where offsets came from, `none` stores no timing).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — laying transcripts onto caption tracks while preserving per-word timing — and declares the return shape `{ caption_track_id, cues }`. It is clearly distinguishable from `transcribe_clip` (which produces the envelope) and `correct_caption_text` (which consumes word offsets).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete routing: pass `transcribe_clip`'s envelope as-is, or supply your own cues with `word_timing: 'none'`, and notes that `correct_caption_text` needs word offsets. It does not, however, address when to prefer this over the sibling `apply_subtitles`, so an explicit alternative exclusion is missing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

auto_split_by_shotA
Destructive

Split a VideoClip at cached analyze_clip shot cuts as one edit. min_shot_us defaults to 500000. drop_short deletes shorter shots and overlapping link members. Returns layer_ids in timeline order, or the original ID when no interior cut exists.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesThe VideoClip to split.
drop_shortNoAlso delete segments shorter than min_shot_us, with the overlapping members of their link. Default false.
min_shot_usNoShortest shot to keep; default 500000, µs.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With destructiveHint=true already declared, the description adds genuinely useful context beyond the annotation: 'as one edit' conveys single-undo semantics, and it specifies that drop_short also removes overlapping link members, which is a non-obvious destructive side effect. Return behavior is also disclosed. Missing only whether the original clip is consumed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight, front-loaded sentences with the purpose first. Minor waste: the min_shot_us default and drop_short semantics duplicate the schema verbatim, but nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by documenting the return contract (layer_ids in timeline order, or the original ID when no interior cut exists). Combined with the destructive annotation and 100% schema coverage, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents all three parameters including the 500000 default and drop_short's link-deletion behavior. The description largely restates the schema, adding no new format, units, or edge-case detail, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (split), resource (VideoClip), and the distinguishing source of cut points (cached analyze_clip shot cuts), explicitly contrasted with a generic split by noting 'as one edit'. This lets an agent tell it apart from split_layer and analyze_clip without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'at cached analyze_clip shot cuts' implies the prerequisite that analyze_clip must have run, but the description never states when to choose this over split_layer or trim_layer, nor any exclusions. Usage is inferable but not spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

begin_agent_sessionA

Begin a work session and show the lightweight agent view. Creates one Pre-agent checkpoint. Repeating on the same connection returns the existing session without changing the view; another connection is refused (AgentSessionBusy names the holder) unless it takes over with end_agent_session { force: true }. Finish with end_agent_session; a session whose connection is gone is closed by the app once its stream has dropped. The user may switch views without ending the session. Unrecorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonYesWhat this work session is for; shown to the user beside the busy badge.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the single destructiveHint=false annotation, the description discloses idempotency on repeat calls, connection-based exclusion semantics, takeover behavior, auto-cleanup when the stream drops, and that the view may be switched without ending the session. It even notes 'Unrecorded,' which is a meaningful behavioral trait. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence adds value: purpose, checkpoint creation, connection semantics, takeover path, cleanup behavior, view flexibility, and recording state. It is front-loaded with the primary purpose and avoids redundant or filler language.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a session-management tool with one parameter and no output schema, the description covers the essential behavioral contexts: what happens on first call, repeat call, competing connection, and connection loss. It also names the exact takeover mechanism and the cleanup condition, making it fully usable by an agent without needing to infer behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the only parameter, 'reason,' is already documented in the schema as 'What this work session is for.' The description repeats this by saying it is shown beside the busy badge but adds no new semantic meaning beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Begin a work session'), the resource (the agent session), and what it does visually ('show the lightweight agent view'). It also mentions creating a Pre-agent checkpoint, distinguishing this from ordinary session tools and from sibling checkpoint tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit lifecycle guidance: reusing the same connection returns the existing session, a different connection is refused, and takeover requires end_agent_session { force: true }. It also directs the user to finish with end_agent_session and explains when the app auto-closes the session, leaving no ambiguity about when and how to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clear_keyframesA
Destructive

Collapse a param's animation back to a single Static value. value (optional) is the value to hold, typed by param_key — a number, or {r,g,b,a} (integers 0..255) for "color"; when omitted, defaults to the first keyframe's value. No-op on an already-Static track.

ParametersJSON Schema
NameRequiredDescriptionDefault
valueNoThe value to hold, typed by `param_key`; omit for the first keyframe's value.
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, and the description usefully adds that the call is a no-op on an already-Static track, so the agent knows the destructive scope is limited to animated tracks. It also documents the default when `value` is omitted. It does not mention undo/reversibility, so it stops short of full disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the core action, then typing details, then the no-op caveat. No filler and nothing that restates the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-param mutation tool with no output schema and a destructiveHint annotation, the description covers behavior, typing, and idempotency adequately. Scoping (only the named param on the named layer is affected) is inferable but not stated, and reversibility is unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so baseline is 3, but the description adds real meaning beyond the schema: the color object shape ({r,g,b,a}, integers 0..255) and the omission default of holding the first keyframe's value. That is the one piece of type information the schema description leaves implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource: "Collapse a param's animation back to a single Static value." An agent can readily distinguish this from siblings like delete_keyframe, update_keyframe, or smooth_keyframes because the outcome (a single held value) is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the semantics plus the "No-op on an already-Static track" condition, which tells the agent the operation is safe to call idempotently. However, no alternatives are named — e.g. it never says to use delete_keyframe/update_keyframe instead when the caller wants to edit rather than flatten a track.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compare_framesA
Read-only

Compare two video frames for perceptual similarity — dedup shots, match a cutaway. Each side is { layer_id, t_us }: a VideoClip layer and a SOURCE-ABSOLUTE µs timestamp (the space analyze_clip's keyframe_t_us and media://{id}/frame/<t_us> use); the two may be the same clip or different clips. Returns { phash_hamming, ssim, similar }: phash_hamming is the 0..64 distance between the frames' perceptual hashes (0 = identical, 20+ = a different scene), ssim is structural similarity 0..1, and similar is phash_hamming <= 10 && ssim >= 0.5. Read-only; VideoClip layers only, errors naming the offending side.

ParametersJSON Schema
NameRequiredDescriptionDefault
aYesFirst frame to compare.
bYesSecond frame to compare.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnlyHint=true, and the description reinforces this with 'Read-only', which is consistent. It goes beyond annotations by disclosing the return format (phash_hamming, ssim, similar) with explicit thresholds and ranges, the fact that the two sides can be the same or different clips, and that errors name the offending side. This is rich, actionable behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph with zero filler. It front-loads purpose, then covers parameter semantics, return semantics, and constraints in a logical flow. Every sentence carries necessary information, and it avoids restating the tool name or generic phrasing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with nested objects, no output schema, and a specific timestamp convention, the description covers all bases: use cases, parameter interpretation, return fields with thresholds, the read-only nature, and error behavior. An agent can invoke it correctly without needing to inspect other documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with clear per-property descriptions, so baseline is 3. The description adds value by clarifying the timestamp space ('SOURCE-ABSOLUTE µs' and cross-referencing analyze_clip's keyframe_t_us and media:// URLs) and by noting the sides may be same or different clips. This goes beyond the schema's basic 'Target VideoClip layer id' and 'microseconds' phrasing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb+resource ('Compare two video frames for perceptual similarity') and adds concrete use cases (dedup shots, match a cutaway). It is the only tool in the sibling set that performs frame comparison, so it is naturally distinguished; it also clarifies that it works on VideoClip layers, removing ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly gives usage contexts (dedup shots, match a cutaway) and states a hard constraint ('VideoClip layers only'), which helps the agent decide when to call it. However, it does not name an alternative tool to prefer in other cases, nor does it say when NOT to use it beyond the layer-type restriction. Still, the intended scenarios are clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

correct_caption_textA

Correct the captions against the project's reference text — set_project_settings { correction_script } — and re-segment the cues the correction changed. Returns { changed }, counting a re-segmented group whole. Refused while the script is blank (InvalidArgument, field correction_script). Every caption in the composition by default; layer_ids narrows it (a non-caption id refuses the call). A cue with word timing (see apply_transcripts) may be SPLIT or MERGED to match the new wording, each timed from its words; one without it is corrected in place. Refuses whole, before any write, if a target or its track is locked. One recorded edit.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idsNoThe captions to correct. Omit for every caption in the composition.
composition_idNoComposition whose captions are meant — a Group's id from `project://compositions`; omit for the root.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only `destructiveHint: false` in annotations, the description carries the behavioral burden and does so thoroughly. It discloses blank-script refusal, pre-write whole-call refusal on locked targets, split/merge behavior based on word timing, return shape, and the fact that the operation records exactly one edit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and includes only valuable details, but the middle section packs many clauses into a dense, em-dash-heavy sentence. It is still efficient, but slightly harder to parse than necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex mutation tool, the description covers defaults, scoping, invalid input behavior, lock handling, word-timing effects, return value semantics, and side-effect granularity. No output schema exists, so the explicit `Returns { changed }` note is essential and present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema description coverage is 100%, the description adds meaningful semantics: omitting `layer_ids` means all captions, a non-caption id refuses the call, and `composition_id` refers to a Group id from `project://compositions`. This goes well beyond the schema's basic property descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb and resource: correct captions against the project's reference text using the configured correction script. It also distinguishes the tool from sibling operations by mentioning re-segmentation, word timing, and refusal conditions, so an agent can tell what this tool uniquely does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides strong usage context: the tool works on all captions by default, `layer_ids` narrows scope, non-caption ids are refused, and the correction script must be configured. It references `apply_transcripts` and `set_project_settings` for related concepts, but it does not explicitly contrast this tool with alternatives like `merge_captions` or `restyle_captions`.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_checkpointA

Create a named checkpoint of the current state and return { checkpoint_id, label }. Checkpoints survive later commits (unlike the redo tail) and persist in the project file; the agent panel shows each as a row with a Restore button. Use it at logical batch boundaries. Unrecorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelYesCheckpoint name.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description discloses that checkpoints persist in the project file, survive later commits, are shown in the agent panel with Restore buttons, and return a specific object. It also includes the notable 'Unrecorded' behavioral trait. This provides substantial behavioral context that annotations alone do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no wasted words. The primary action and return value are front-loaded, followed by persistence details, panel behavior, usage guidance, and the important 'Unrecorded' note. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter creation tool with a non-destructive annotation and no output schema, the description is complete. It covers what the tool does, what it returns, persistence, lifecycle behavior, UI representation, and when to use it. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers the only parameter, label, with 'Checkpoint name.' The description adds conceptual context by calling it a 'named checkpoint' and mentioning the returned label, but it does not add syntactic or format details beyond the schema. Baseline 3 is appropriate given full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action and resource: creating a named checkpoint of the current state. It also distinguishes checkpoints from the redo tail by noting they survive later commits, which separates this tool from related concepts. The return value is specified, leaving no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage context: 'Use it at logical batch boundaries.' This tells the agent when the tool is appropriate. It does not explicitly name alternatives or exclusions, but the checkpoint semantics and sibling tools like restore_checkpoint and list_checkpoints make the intended workflow reasonably clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_groupA

Pre-compose selected clips into a new Group, preserving their placement and links. Refuses partial links, locked members and incompatible selections. Returns the Group clip and composition. Group members retain their own timing and effects.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelNoOptional name for the new composition. Omit and the UI derives one.
layer_idsYesThe layers to pre-compose; at least one, all in one composition.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description carries most of the behavioral burden and does so well: it names the three refusal conditions, states that placement and links are preserved, and even discloses the return payload ('the Group clip and composition') in the absence of an output schema. It stops short of explaining what happens to the original layer stack or whether the operation is reversible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tightly packed sentences, front-loaded with the action and followed by constraints and return value. Minor redundancy between 'preserving their placement and links' and 'Group members retain their own timing and effects,' though each carries slightly different information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by naming the return value, and it covers preconditions and preservation semantics for a small two-parameter mutation. It lacks any note on permissions, undo/checkpoint interaction, or effect on the source layers, which would make it fully self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters carry their own descriptions (label optional with UI-derived fallback; layer_ids as at-least-one, single-composition layers). The description adds no parameter-level detail beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Pre-compose selected clips into a new Group') and clarifies that it operates on selected clips rather than layers/tracks generally. It does not explicitly contrast itself with the closely related siblings add_group_layer, add_group_members, or ungroup_layer, so an agent must infer the distinction from names alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by 'pre-compose selected clips,' and the refusal conditions (partial links, locked members, incompatible selections) implicitly tell the agent when the call will fail. However, there is no explicit statement of when to choose this over add_group_layer or ungroup_layer, nor any prerequisite guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_projectA
Destructive

Create <parent_folder>/<name> and open it, as New Project does; only when the user asked. The project open before is saved. Defaults: the session view's default_parent_folder; 1920x1080 at 60 fps (the rate locks once a layer is placed). Returns { name, dir, replaced }.

ParametersJSON Schema
NameRequiredDescriptionDefault
fpsNo24, 25, 30, 50, 60, or 24000/30000/60000 over 1001.
nameYesFolder and project name.
widthNoEven px, 16..7680; with `height`.
heightNoEven px, 16..7680; with `width`.
parent_folderNoAbsolute folder to create in.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark destructiveHint=true; the description adds crucial side-effect context that the previously open project is saved and that the frame rate locks once a layer is placed. It also discloses defaults and the return shape, with no contradiction to annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A dense but efficient paragraph front-loads the create/open action, then adds usage condition, side effect, defaults, and return value. Every sentence contributes to correct invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers the return value despite no output schema and includes side-effect and default information. It leaves some ambiguity around what `replaced` means and does not explicitly route the agent to open_project, so it is strong but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3, but the description adds default values not present in the schema: `default_parent_folder` and 1920x1080 at 60 fps. It also explains the rate-lock behavior, adding useful meaning beyond the parameter definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: creates `<parent_folder>/<name>` and opens it, explicitly analogized to New Project. The create/open action is clear and distinguishable from sibling tools such as open_project.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the condition 'only when the user asked,' which is clear context for invocation. However, it does not name open_project as the alternative for existing projects or state exclusions beyond that condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_checkpointA
Destructive

Drop a named checkpoint. Only the restore point goes — the edits it marked stay, nothing about the timeline or the undo stack changes, so there is nothing to undo afterwards. CheckpointNotFound for an id list_checkpoints does not report. Deliberately NOT blocked by set_history_lock: the lock rejects revert paths, and forgetting a restore point reverts nothing. Unrecorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
checkpoint_idYesCheckpoint id.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide destructiveHint=true, and the description substantially expands on that: deletion is limited to the restore point, edits persist, undo history is unaffected, and the operation is unrecorded. It discloses the CheckpointNotFound error condition and the deliberate non-interaction with history locking. This goes far beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences deliver a large amount of behavioral information with no filler, and the main action is front-loaded. The phrasing 'CheckpointNotFound for an id list_checkpoints does not report' is slightly awkward, but the structure is still tight and readable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter destructive tool with no output schema, the description covers the effect, non-effects, undo implications, error behavior, lock interaction, and undo/recording status. Nothing an agent needs to decide whether to call it or anticipate its consequences is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents checkpoint_id with 100% coverage, giving a baseline of 3. The description adds that the id must be one list_checkpoints reports or CheckpointNotFound is raised, which clarifies the valid value source. This extra error-condition context raises the score above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'Drop a named checkpoint.' It distinguishes the action from restore/revert paths by stating 'Only the restore point goes — the edits it marked stay,' which differentiates it from restore_checkpoint. Clear and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context that dropping a checkpoint does not alter timeline or undo stack, implying it is for cleanup rather than revert. It also explicitly clarifies that set_history_lock does not block this operation, which tells an agent when this tool remains available. It does not name sibling alternatives explicitly, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_compositionA
Destructive

Delete a composition nothing references — an orphan left when its Group layers were deleted. Refuses while any Group layer points at it (CompositionInUse { ref_count }; project://compositions shows the count) and refuses the root (RootComposition). Recorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
composition_idYesComposition id.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The destructiveHint annotation already flags mutating behavior, and the description adds valuable context beyond it: the tool refuses while references exist, includes the CompositionInUse error with ref_count, mentions the root composition exclusion, and notes that the operation is recorded. This meaningfully enriches the annotation-only picture.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler: the main action is first, constraints and failure modes follow, and the 'Recorded' outcome note is a compact final touch. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter destructive tool with a complete schema and a clear annotation, the description fully covers what the agent needs: when it is appropriate, when it will fail, and what happens afterward. No output schema is needed because the behavior is simple and fully disclosed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers the single parameter completely (composition_id with description 'Composition id.'), so the baseline is 3. The description adds no additional parameter-level semantics, but none are needed for such a simple, well-documented parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Delete) and resource (composition), and further narrows the scope to orphaned compositions that nothing references. It clearly differentiates this from sibling tools like delete_layers or delete_track, which operate on other entities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear conditions for use: delete only a composition nothing references, specifically orphans left after Group layer deletion. It also states when the tool refuses to operate (referenced compositions and root), effectively defining exclusions, though it doesn't name an alternative tool explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_effectA
Destructive

Remove an effect from a layer by id.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesLayer id.
effect_idYesEffect id.

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The destructiveHint annotation already marks this as destructive, and the description's 'Remove' is consistent with that. The description adds no further behavioral context such as irreversibility or side effects, but for such a simple deletion there is little additional behavior to disclose.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One focused sentence with no filler. The key action, resource, scope, and parameter mechanism are all communicated efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple two-parameter destructive operation. The description plus schema fully cover what the tool does and what arguments are needed; nothing an agent requires to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and both layer_id and effect_id are described in the schema. The description's 'by id' loosely maps to these parameters but adds no meaning beyond what the schema already provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Remove'), a resource ('effect'), and a scoping detail ('from a layer by id'). This clearly differentiates it from sibling tools like add_effect, update_effect, and move_effect without needing to inspect their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: this tool is for removing an existing effect from a layer using IDs. It does not explicitly name alternatives or say when not to use it, but the operation is unambiguous enough for an agent to route correctly among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_keyframeA
Destructive

Remove a keyframe by id from a layer param. Get the id from get_param_track. When it was the last key, the track collapses to Static holding that key's value.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].
keyframe_idYesKeyframe id.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotation already declares destructiveHint=true, so the safety profile is covered. The description goes beyond that by disclosing the side effect when the removed keyframe was the last one ('the track collapses to Static holding that key's value'), which the agent could not infer from annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, zero filler, with the core action front-loaded and the prerequisite and side-effect following. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-keyframe destructive op with no output schema and full schema coverage, the description covers purpose, the id-prerequisite, and the collapse side effect. It omits reversibility/undo guidance, which for a destructive tool is a minor remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents layer_id, param_key (with full enum/pattern enumeration), and keyframe_id. The description only echoes 'by id' and 'layer param' and adds no format or semantics beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Remove') and resource ('a keyframe by id from a layer param'), and the granularity ('a keyframe', single, by id) implicitly distinguishes it from bulk siblings like clear_keyframes or track-level delete_track.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit prerequisite/routing instruction: 'Get the id from get_param_track,' which tells the agent the upstream workflow needed before calling. It doesn't state any when-not conditions or name a preferred alternative for bulk removal, but the context is clear enough to invoke correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_layersA
Destructive

Delete a set of layers as one recorded edit. ripple decides what happens to the vacated span: false (default) is the lift — it stays empty and nothing moves; true closes each hole so the film gets shorter — every remaining layer starting at or after a hole shifts left by its length on EVERY track of the composition (anchored markers riding along), touching holes merge, and layers starting before a hole, free markers and the playhead stay put. The set is one composition's (CrossCompositionSet); any locked layer or track refuses the whole batch (LayerLocked / TrackLocked); tracks the batch emptied are pruned. A ripple refuses whole, before any write, naming the blocker: RippleInsideHole (a remaining layer starts inside a hole — add it to layer_ids, or lift), RippleCollision (a mover would land on a layer that is not moving), RippleLinkStraddles (a link spans the hole), RippleLockedLayer (only a layer that actually shifts blocks). An empty set records nothing as a lift and is refused as a ripple.

ParametersJSON Schema
NameRequiredDescriptionDefault
rippleNoClose each vacated span and shift everything downstream left (default false — leave the spans empty).
layer_idsYesThe layers to delete, all in one composition.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only destructiveHint=true, yet the description discloses the full behavioral profile: atomic all-or-nothing refusal naming the specific blocker (LayerLocked, TrackLocked, RippleInsideHole, RippleCollision, RippleLinkStraddles, RippleLockedLayer), pre-write validation, track pruning, marker/playhead behavior, and the empty-set edge case.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The ripple semantics are front-loaded before the error catalog, and every sentence carries information. It is dense but not padded; the long single paragraph and back-to-back parenthetical error codes slightly hurt scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive batch-mutation tool with no output schema, the description covers defaults, atomicity, side effects (track pruning, downstream shifts), and the complete failure taxonomy, leaving nothing an agent needs to call it correctly unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, but the description goes well beyond the schema's one-line ripple definition by specifying exactly what shifts (every remaining layer at/after a hole, on every track, anchored markers riding along, free markers and playhead unaffected), how touching holes merge, and how layer_ids interacts with the ripple refusal cases.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first clause states a specific verb and resource ('Delete a set of layers') plus the salient semantic detail that it is 'one recorded edit'. An agent can distinguish this from siblings like shift_layers or ripple_delete_gap, which operate on gaps rather than a batch of layers.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description thoroughly explains the when-to-choose decision between the two modes: ripple=false leaves the span empty, ripple=true closes holes and shortens the film. It does not explicitly name alternative sibling tools (e.g. ripple_delete_gap) or say when not to use this tool, so it falls short of 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_markerC
Destructive

Remove a marker.

ParametersJSON Schema
NameRequiredDescriptionDefault
marker_idYesMarker id.

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotation already declares destructiveHint=true, so the agent knows it is destructive. However, the description adds no extra behavioral context beyond that—no mention of irreversibility, confirmation, or side effects. It essentially restates the action without enriching the agent's understanding.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that conveys the core action with no wasted words. It is appropriately sized for a simple delete operation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter destructive tool with annotations covering the destructiveness, the description is minimally adequate. However, it could mention that the deletion is permanent or that it targets a specific marker by ID, but given the schema and annotations, it is sufficient for basic use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides 100% coverage of the single parameter (marker_id) with a description, so the baseline is 3. The tool description adds nothing about the parameter, but the schema already handles it adequately.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Remove') and resource ('a marker'), which distinguishes it from siblings like add_marker and update_marker. It is specific enough to know the action, though it doesn't specify any additional scope or conditions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives like update_marker or set_marker_anchor. The description does not mention contexts, prerequisites, or conditions, leaving the agent to infer usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_mediaA
Destructive

Remove a media item. Rejects if any layer references it unless force=true. With force=true, also deletes the referencing layers in one atomic commit, exactly as delete_layers would: their links dissolve below two members, a transient lane they empty is pruned, a locked lane refuses as TrackLocked. Unrecorded when nothing used it; the forced cascade records.

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoAlso delete the layers that use it (their links and emptied lanes go too). Default false: media in use refuses.
media_idYesMedia id.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotation only provides `destructiveHint: true`, but the description goes far beyond that: it discloses the rejection unless force, the atomic commit, link dissolution below two members, transient lane pruning, TrackLocked refusal, and recording behavior. This is exactly the kind of side-effect disclosure an agent needs for a destructive operation, and it does not contradict the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence contributes: the core action, the conditional, the cascade specifics, and the recording behavior. It is front-loaded with the primary purpose and organized logically from the basic operation to edge-case details, with no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with no output schema, the description covers the main behavior, failure modes (rejection, TrackLocked), and side effects (links, lanes, recording). The only notable omissions are the success return (if any) and behavior for a non-existent media_id, though these are minor for a delete operation and the description is otherwise quite complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds substantial meaning beyond the schema's `force` description. It details the atomic commit, the exact behaviors of links/lanes, and the recording distinction, which the schema only vaguely refers to ('their links and emptied lanes go too'). This gives the agent a much richer understanding of the parameter's consequences.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Remove a media item.' It then clarifies the conditional behavior with `force`, making the tool's core function unmistakable. It also distinguishes itself from the sibling `delete_layers` by referencing that tool's behavior in the cascade, so an agent can tell them apart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly explains when `force=true` is needed (when layers reference the media) and what the default rejection means. It also evokes `delete_layers` as the analogous cascade behavior. However, it does not explicitly state 'use delete_layers when you only want to delete layers and keep media' or otherwise draw a direct when-to-use line between the siblings, leaving that to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_motifA
Destructive

Delete an installed or draft user Motif by id. Built-ins and unknown ids are refused (list_motifs reports what exists). Placed layers referencing it degrade to an error placeholder.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe Motif id (from `list_motifs`).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With destructiveHint=true, the description adds crucial context: it refuses built-ins and unknown ids, and explains that placed layers referencing it degrade to an error placeholder. This goes beyond the annotation, informing the agent of consequences.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with the action and scope, then important constraints and consequences. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter destructive tool, this is complete. It identifies the target, valid sources of id, refusal conditions, and downstream effects, leaving nothing essential unknown.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already fully covers the id parameter (100% coverage), but the description reinforces that the id should come from list_motifs, adding practical guidance on how to obtain a valid id, which is slightly beyond the schema description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool deletes a Motif by id, specifying that it applies to installed or draft user Motifs and that built-ins and unknown ids are refused. It also references list_motifs for what exists, distinguishing it from other sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies when to use: to delete an installed or draft Motif, and when not: built-ins or unknown ids are refused. It doesn't explicitly mention alternatives, but the context is clear enough for an agent to know this is the deletion action.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_trackA
Destructive

Remove a track. Refuses a track with layers unless force=true (TrackNotEmpty); with force the layers go with it and their links are cleaned up in the same undo entry. A Group layer among them leaves its composition in place with ref_count 0 (project://compositions) — delete_composition removes that. Only A roll / B roll tracks are protected (TrackNotRemovable); audio and caption tracks can be deleted.

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoAlso delete the layers still on it. Default false, which refuses a non-empty track (TrackNotEmpty).
track_idYesTrack id.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare `destructiveHint=true`, so the description carries the real behavioral load and does so richly: error codes, cascade behavior (layers deleted with the track), link cleanup folded into the same undo entry, Group-layer `ref_count 0` semantics, and the A/B-roll-only protection rule. This is well beyond what the annotation conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, front-loaded with the core action, each covering a distinct edge case (refusal, cascade, group composition, protected track types). No filler or repetition despite the detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with only a destructiveHint annotation and no output schema, the description covers everything an agent needs: preconditions, force semantics, cascade and link side effects, undo scoping, and the protected-track exception.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description earns extra credit by describing the *consequences* of `force=true` (layers go with it, links cleaned up in one undo entry) rather than just restating the boolean's default and refusal behavior already in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Remove a track") and immediately scopes it against siblings by describing the refusal path, the protected track classes, and routing the leftover composition to `delete_composition`. An agent can distinguish this from `delete_layers` and `delete_composition` without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when the tool refuses (non-empty track, `TrackNotEmpty`) and how `force=true` changes the outcome, plus names `delete_composition` as the follow-up for an orphaned Group composition. It does not explicitly compare against `delete_layers` for the case where the caller wants to keep the track, leaving one inference to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_transitionA
Destructive

Remove a transition and restore the hard cut, routed by provenance: the outgoing layer's end shrinks back by extended_us (only borrowed tail is returned, never real content) and the incoming layer moves RIGHT by duration_us − extended_us, link siblings following. TransitionRestoreCollision when that destination has since been filled — move or delete the blocker first; the system never makes room. Recorded. TransitionNotFound for an unknown id.

ParametersJSON Schema
NameRequiredDescriptionDefault
transition_idYesTransition id.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The destructiveHint annotation already signals destruction, but the description adds valuable context: provenance-based shrinkage, layer movement, and the fact that the system never makes room. It also notes the action is recorded and lists error types, going beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and technically detailed. While every sentence adds information, it is longer than necessary for a delete operation and could be tightened. The core action is front-loaded, but the paragraph format makes it less scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter destructive tool with no output schema, the description covers the mechanical behavior, error cases (TransitionRestoreCollision, TransitionNotFound), and recording status. It does not explicitly state return values, but for a delete action this is often implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for transition_id, so the baseline is 3. The description does not add new info about the parameter itself, but it references internal fields like extended_us and duration_us that explain the operation's mechanics, which is acceptable since the parameter is straightforward.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Remove' with the resource 'transition' and the outcome 'restore the hard cut'. It distinguishes this from sibling tools like add_transition and update_transition by describing the specific deletion behavior and provenance routing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The tool's purpose is obvious from the description, and it explicitly provides handling for the TransitionRestoreCollision error by advising to move or delete the blocker first. It does not explicitly name alternatives, but the context of siblings makes it clear this is for removal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

describe_clipA
Read-only

Describe a VideoClip layer's visual content as timestamped, open-vocabulary segments with a video-understanding model (local Qwen3-VL / MiniCPM-V via llama-mtmd-cli, or an OpenAI-compatible endpoint). Samples frames at fps (default 1.0) and runs the model once over the window. Returns { backend, model, segments: [{ t_start_us, t_end_us, text, tags }] } in SOURCE-ABSOLUTE µs; text is prose, tags short visual keywords (subjects, setting, camera, shot type). Cached per source range. Optional t_start_us/t_end_us narrow the window; focus ("general" | "shot-type") picks the prompt that fills tags; language is a BCP-47 tag for the output (default: the app's UI language) and part of the cache key. backend ("qwen3_vl" | "minicpm_v" | "byo_endpoint") REQUIRES that engine — it errors naming the missing binary / model / endpoint rather than substituting, so a local choice never uploads frames; omitted, the user's preferred engine then availability (local first). Retimed clips map their selected window onto source time. A missing engine is refused, naming the gap.

ParametersJSON Schema
NameRequiredDescriptionDefault
fpsNoFrames sampled per second (higher = finer, costlier; capped to the model's context). Default: the app's setting, else 1.0. Cache key.
focusNo`"general"` or `"shot-type"` (biases `tags` toward shot type / camera). Default: the app's setting, else `"general"`. Cache key.
backendNoStrict engine override: `"qwen3_vl"` | `"minicpm_v"` | `"byo_endpoint"`. That engine serves or the call errors; nothing is substituted. Omitted: the user's preferred engine, then availability.
languageNoBCP-47 tag the `text` and `tags` come back in (`"en-US"`, `"zh-CN"`, `"ja"`). Default: the app's UI language. Cache key.
layer_idYesTarget VideoClip layer id.
t_end_usNoOptional window end in timeline microseconds. Defaults to the layer's `t_end_us`. Must lie within the layer.
t_start_usNoOptional window start in timeline microseconds. Defaults to the layer's `t_start_us`. Must lie within the layer.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnlyHint annotation: discloses caching (per source range, keyed by fps/focus/language), strict backend behavior that errors rather than substitutes, error messages naming the missing binary/model/endpoint, and remapping of retimed clips onto source time. This is unusually rich behavioral context for a read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and return shape, then details parameters; every sentence carries information. It is dense and parenthetical-heavy (engine names, defaults, cache-key notes), which slightly hurts scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies the full return contract (`{ backend, model, segments: [...] }` with field meanings and source-absolute microseconds), plus defaulting, caching, and failure behavior. Nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it explains what focus does to the returned tags, that language is a BCP-47 tag and part of the cache key, that backend is a strict override, and that fps sampling is capped to the model's context. It largely mirrors rather than exceeds the schema, hence 4 rather than 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (describe), resource (VideoClip layer), and output shape (timestamped open-vocabulary segments), and names the model family doing the work. This is clearly distinguishable from siblings like analyze_clip, transcribe_clip, and analyze_audio, which cover other modalities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the sampling model, the optional windowing, and the privacy-relevant consequence of choosing a local backend (frames never uploaded), which all inform when to pick this tool. It never explicitly names a sibling to prefer or a when-not-to-use condition, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

detect_pausesA
Read-only

Find the pauses in a clip's audio — the stretches nobody is speaking — from the pre-computed waveform. Read-only: the write is remove_pauses (cut them) or add_marker (mark them). A pause is a run where every channel's peak stays below threshold_amp for at least min_pause_us; a loud run shorter than bridge_us inside it (a click, a cough) does not end it. Defaults threshold_amp=0.02 (-34 dBFS), min_pause_us=500000, bridge_us=80000 (must be below min_pause_us). layer_id is an Audio layer, or a VideoClip, which resolves to the Audio layer of its link (refused when it plays no sound). Returns { pauses: [{ t_start_us, t_end_us }], noise_floor_amp, peaks_source }, timeline-absolute µs, sorted; noise_floor_amp is the 10th-percentile peak (a threshold reads well at the floor + 6 dB); peaks_source is "raw" or "fx" (baked effect chain). Errors until the waveform job finishes — wait for media:job_complete with kind=waveform and retry.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesTarget Audio layer id. A VideoClip id is accepted by the host, which resolves it to the Audio layer of its link before the call.
bridge_usNoA loud run shorter than this (µs) inside a quiet run does not end the pause. Default 80000 (80ms). Must be ≥ 0 and below `min_pause_us`.
min_pause_usNoShortest pause to surface, in microseconds. Default 500000 (0.5s).
threshold_ampNoPeak amplitude threshold in [0.0, 1.0]. Anything strictly below this counts as quiet. Default 0.02 (≈ -34 dBFS).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description reinforces it with 'Read-only'. It adds substantial behavioral context beyond annotations: the exact detection algorithm (peak below threshold_amp for min_pause_us, bridge_us exception), the return shape, timeline-absolute µs, sorted order, noise_floor_amp meaning, peaks_source values, and the error/retry condition. This is rich, non-redundant behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: purpose, read-only distinction, algorithm, defaults, layer resolution, return format, and error handling. It is front-loaded with the core purpose and the read-only note, then flows logically into parameters and behavior. No filler or repetition of schema text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only detection tool with no output schema, the description is complete: it explains the return value shape, units, sorting, the meaning of derived fields, the error condition, and the retry strategy. An agent has everything needed to call it correctly and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters. The description adds value by explaining the algorithm's semantics (how threshold_amp, min_pause_us, and bridge_us interact) and by clarifying that layer_id accepts a VideoClip that resolves to its linked Audio layer and is refused when it plays no sound. This goes beyond the schema's field-level descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Find'), a specific resource ('pauses in a clip's audio'), and the exact detection criteria. It also distinguishes itself from siblings by naming remove_pauses and add_marker as the write counterparts, so an agent can tell it apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use this tool (to find pauses) and names alternatives (remove_pauses to cut, add_marker to mark). It also gives operational guidance: wait for media:job_complete with kind=waveform and retry if the waveform job hasn't finished. This is clear context with exclusions and alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

dry_runA
Read-only

Run a sequence of edit operations against a clone of the project WITHOUT committing — check overlaps and invariants before touching real state. Validates after each op exactly as commit() does and HALTS at the first error. Returns { results: [{ index, status, output? | error? }], halted_at: number | null }. Supported ops: add_color_layer, add_video_layer, add_audio_layer, add_text_layer, update_layer, update_layer_params, move_layer, split_layer, delete_layers (lift only — ripple: true is refused), add_transition (the transition kind rides as transition_kind, since kind names the op). Motifs, caption import, media import and undo/redo are not dry-runnable.

ParametersJSON Schema
NameRequiredDescriptionDefault
operationsYesThe edits to rehearse, in order.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the readOnlyHint annotation by disclosing that it validates after each op, halts at the first error, and returns a specific `{ results, halted_at }` shape. It also documents refusal behavior for `ripple: true` and the special `transition_kind` handling, providing rich behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but efficiently organized: the core behavior is front-loaded, and the supported-ops list and return type are packed into compact, readable sentences. Every clause earns its place, and the use of backticks and inline examples aids comprehension without bloat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, the description is complete: it specifies the clone-and-validate behavior, the halt condition, the return shape, the full set of supported operations, and the exclusions. It also references the per-op schemas indirectly via 'that tool's args', so an agent can combine this definition with the sibling tool schemas without missing any needed information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though schema coverage is 100%, the description adds meaning beyond the schema by listing the exact supported operation kinds and explaining that add_transition uses `transition_kind` because `kind` names the op. It clarifies the expected shape of each operations array item and what values are valid.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Run a sequence of edit operations against a clone of the project WITHOUT committing.' This clearly differentiates dry_run from the many actual mutation tools among the siblings, and the phrase 'before touching real state' reinforces that it is a rehearsal, not a real edit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when to use the tool ('check overlaps and invariants before touching real state'), what it supports (a specific list of ops), and what it refuses ('ripple: true is refused'). It also names non-dry-runnable operations, giving clear exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

end_agent_sessionA

End your work session and release its history lock. Keeps the current view and activity records. Does not cancel running tasks, disconnect MCP, or prohibit later calls. Only the owning connection may end a session — unless force: true, which takes over another connection's session (and its lock) when its owner is gone; read_project { view: "session" } shows who holds it. Unrecorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoEnd another connection's session too. Default false.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Behavioral details go well beyond the `destructiveHint: false` annotation: the description explains that the history lock is released, the current view and activity records are kept, running tasks are not canceled, MCP is not disconnected, later calls are not prohibited, and the action is 'Unrecorded.' It also discloses the force behavior and the ownership condition, giving a complete picture of side effects and limitations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is tightly packed with information in a logical flow: core action, then clarifications of non-effects, then ownership/force rules, then a pointer to read_project, and a final note on recording. Every sentence earns its place, and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 1-optional-parameter tool with no output schema, this description is complete. It covers the action, side effects, ownership rules, force semantics, how to check ownership, and the unrecorded nature. An agent has all necessary information to correctly invoke the tool and decide whether force is appropriate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the schema already describes the `force` parameter as 'End another connection's session too. Default false.', the description enriches it with context: `force: true` takes over another connection's session (and its lock) when its owner is gone. This explains the intended use case and adds meaning beyond the schema, outweighing the high schema coverage baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'End your work session and release its history lock,' a specific verb-resource pair that clearly states the tool's core action. It further distinguishes itself from siblings like begin_agent_session and set_history_lock by focusing on session termination and lock release. The addition of what it does not do (cancel tasks, disconnect MCP, prohibit later calls) removes ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance by clarifying that only the owning connection may end a session and that `force: true` is for when the owner is gone, pointing to `read_project { view: "session" }` as the way to check ownership. It also implicitly states when not to use it (e.g., if you need to cancel tasks) by listing non-effects. This gives an agent clear decision criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_captionsA
Read-only

The captions of a composition as a subtitle document — format srt or vtt — read from every caption lane (or one track_id) in time order, with the cue text as it stands. Returns { format, cues, body }; write body to a file yourself. Records nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
formatYesSubRip or WebVTT.
track_idNoOne caption lane only; omit for every caption lane of the composition.
composition_idNoComposition whose captions are meant — a Group's id from `project://compositions`; omit for the root.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the `readOnlyHint` annotation, the description adds meaningful behavioral context: it 'Records nothing' and explicitly says the caller must write `body` to a file themselves. It also discloses that captions are returned in time order and that cue text is 'as it stands,' which prevents assumptions about retiming or normalization.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it states the output type, the source and ordering, the return payload, the caller's required follow-up, and the side-effect guarantee. Each sentence adds distinct necessary information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Because there is no output schema, the description correctly explains the return contract as `{ format, cues, body }` and tells the agent how to use `body`. It covers lane selection, ordering, and read-only guarantees; the only minor omission is the internal shape of the `cues` array, which is not essential for writing `body` to a file.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters are already well documented. The description reinforces the meaning of `format`, `track_id`, and composition selection, and adds the time-order behavior, but it does not provide substantial parameter-specific detail beyond what the schema already supplies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool returns the captions of a composition as a subtitle document, with `format` restricted to `srt` or `vtt`. It also defines the source scope (all lanes or one `track_id`) and ordering, which clearly distinguishes it from caption-mutating siblings like `apply_subtitles` or `restyle_captions`.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool: when you need a subtitle document from existing caption lanes and want the cue text as-is. It does not explicitly name alternatives or state when not to use it, but the read-only export framing and 'Records nothing' signal the correct use case without needing further inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

extract_clip_audioA
Read-only

Extract a VideoClip or Audio layer's ORIGINAL source audio — before gain, mute, effects or mixing — for an agent running its own speech model; no engine or API key is involved and nothing is uploaded. Returns a JSON metadata block (layer_id, media_id, t_start_us, t_end_us, source_in_us, source_out_us, duration_us, playback_rate, sample_rate_hz, channels, bits_per_sample, byte_length, mime_type) plus an MCP audio block: base64 WAV, mono 16 kHz 16-bit, starting at zero. Optional t_start_us/t_end_us are composition-absolute µs, defaulting to the layer endpoints; at most 60 s of source audio per call — timeline windows ≤ 60 s / playback_rate. Map source-WAV offsets as t_start_us + offset / playback_rate, then apply_transcripts. Refuses a layer with no audio, a window outside the layer (a VideoClip's audio is its own stream, not its linked Audio layer).

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesTarget VideoClip or Audio layer id.
t_end_usNoExclusive window end in the owning composition's absolute microseconds. Defaults to the layer end. Maximum window duration: 60000000 us (60 s).
t_start_usNoWindow start in the owning composition's absolute microseconds. Defaults to the layer start. Must lie inside the layer.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover readOnlyHint=true; the description adds rich behavioral context: it never uploads anything, refuses layers with no audio, caps windows at 60 s, returns a specific JSON metadata shape plus an MCP audio block, and describes the conversion (mono 16 kHz 16-bit). This far exceeds what the annotation provides.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose but then packs a dense parenthetical field list, a units note, a default note, a window formula, and refusal conditions into one long paragraph. Every sentence carries information, but the density and the inline field enumeration make it harder to scan than necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a 3-param tool with no output schema, the description supplies the return shape, the audio encoding, the default behavior, the window limit, the source-offset mapping formula, and refusal conditions. An agent has everything needed to call it correctly and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds meaning beyond the schema: it explains that t_start_us/t_end_us are composition-absolute µs, default to layer endpoints, and that the window cannot exceed 60 s of source audio (which depends on playback_rate). It also warns that a VideoClip's audio is its own stream, not its linked Audio layer.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('Extract a VideoClip or Audio layer's ORIGINAL source audio') and adds a scope qualifier ('before gain, mute, effects or mixing') that distinguishes it from siblings like analyze_audio, separate_audio_to_new_track, and transcribe_clip. The distinction from transcribe_clip is reinforced by 'for an agent running its own speech model; no engine or API key is involved.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly signals when to use it ('for an agent running its own speech model') and implicit alternatives (transcribe_clip, analyze_audio) via the 'no engine or API key' framing. However, it never names a sibling or states explicit exclusions, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_frame_interpolation_capabilitiesA
Read-only

Query Preview or Export interpolation support per clip, including refusal reasons for unavailable modes.

ParametersJSON Schema
NameRequiredDescriptionDefault
purposeYesRender purpose.
layer_idsYesExplicit target clips

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already establishes this is a safe read, so the bar is lower; the description still adds value by disclosing that the result includes refusal reasons for unavailable modes. It does not describe the result shape in detail, but for a non-mutating query that is acceptable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single compact sentence that front-loads the action and scope, with zero filler. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description's mention of refusal reasons partially compensates for the missing return documentation. For a two-parameter read-only query with fully described params and a safety annotation, that is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (purpose enum, layer_ids) are already documented in the schema. The description's 'Preview or Export' and 'per clip' wording mirrors that without adding syntax or format detail, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

State's a specific verb ('Query') and resource ('Preview or Export interpolation support per clip'), so an agent can distinguish it from the write-side sibling set_frame_interpolation. It stops short of naming that sibling explicitly, which is the only thing keeping it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Query ... support' implies a pre-check before calling set_frame_interpolation, and 'refusal reasons for unavailable modes' hints at diagnostic use. However, no explicit when-to-use, prerequisites, or named alternative is given, leaving usage to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_motif_sourceA
Read-only

Read a Motif's source { manifest, html } — any built-in, installed, or draft. Read this before editing so you can base your changes on the current source. id comes from list_motifs.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe Motif id (from `list_motifs`).

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, and the description reinforces this with 'Read' and 'before editing', which clarifies the non-destructive intent. It adds useful context beyond the annotation by specifying the source shape ('{ manifest, html }') and the motif kinds covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each earning its place: the core action, the behavioral guidance, and the parameter source. No filler or repetition beyond the schema's id note.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read-only tool with a simple input schema, the description is complete. It states what will be read, the scope of motifs, when to call it, and where the id comes from. The absence of an output schema is mitigated by the inline '{ manifest, html }' shape.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already states 'The Motif id (from `list_motifs`)'. The description repeats the same guidance for `id`, adding no new semantic detail beyond what the schema provides. Baseline 3 applies because the schema carries the load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Read') and resource ('a Motif's source'), and states the scope ('any built-in, installed, or draft'). This clearly distinguishes it from list_motifs (listing) and write_motif_draft (writing), even without naming them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: 'Read this before editing so you can base your changes on the current source.' It also tells the agent where the id comes from ('`id` comes from `list_motifs`'), but it does not explicitly describe when not to use it or name alternative tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_param_trackA
Read-only

Read a layer param's animation track — the record to inspect before editing keys. Returns {"mode":"Static","value":v} or {"mode":"Keyframed","extrapolate":{before, after},"keyframes":[{id, t_us, t_local_us, time_fraction?, value, in, out, continuity, segment, preset_id?}]}. t_us is timeline-absolute, t_local_us layer-local; value is typed by param_key. Per key, in/out are the arriving/leaving tangents {x, y, mode} in the segment's unit square ("Auto" = solved on write, "Free" = authored), continuity is "Smooth" | "Broken", segment is the class of the segment leaving the key ("Spline" | "Hold" | "Linear" | "Elastic" | "Bounce"; only Spline reads tangents), and preset_id names the easing preset the leaving segment exactly matches (absent on a hand-tuned curve and the last key). Position params are mode-specific: x/y in XY mode, path_progress in Path mode (a fraction, not a percentage).

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already covers safety. The description goes beyond that by giving the full return shape (Static vs Keyframed), explaining tangent semantics, continuity, segment classes, and that preset_id is absent on hand-tuned curves and the last key. This is rich behavioral context for a read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with purpose and a return example, but the long third sentence is a dense run-on detailing many nested fields (in/out, continuity, segment, preset_id). Every detail is arguably relevant, yet the structure is packed rather than scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of explaining the return, and it does so thoroughly, including field-by-field semantics. It omits pagination or error behavior, but for a read track call this is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both params, giving a baseline of 3. The description adds mode-specific context for position params (x/y in XY mode, path_progress in Path mode as a fraction not a percentage), which is useful but not tied to the required layer_id/param_key mechanics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: read a layer param's animation track. It also frames its role in the workflow ('the record to inspect before editing keys'), which orients the agent without needing any sibling schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'the record to inspect before editing keys' implies the read-before-write workflow, but no explicit when-to-use/when-not guidance and no named alternative (e.g., set_param_track) are provided. Usage is inferable but not stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_mediaA

Import ONE media file from an absolute path. Hashes the file (blake3) and probes metadata via ffprobe when installed. Returns { media_id, kind, label, path, duration_us, width, height, has_audio }; a subtitle document (.srt/.vtt/.ass) is laid onto a caption track instead and returns { caption_track_id, cues }. A directory, a missing path or an unreadable file is refused by name before anything is written; a read that fails mid-import rolls the provisional pool row back. Unrecorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to a video / audio / image / subtitle file the host can read.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Richly discloses behavior beyond annotations: hashing with blake3, conditional ffprobe metadata probing, special subtitle handling, validation refusals before writing, rollback of provisional rows on failed reads, and 'Unrecorded' state. This goes well beyond the single destructiveHint=false annotation and provides no contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is information-dense but well-structured: purpose, processing behavior, return shapes, error handling, and record state. Every sentence adds value, and the primary purpose is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description fully documents return values for both media files and subtitle documents, and covers failure modes including invalid paths and interrupted reads. This is complete enough for an agent to invoke the tool correctly without additional inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the single 'path' parameter is well documented in the schema. The description reinforces the absolute-path requirement and adds the subtitle special case, but the schema already carries the semantic load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description uses a specific verb ('Import') and resource ('ONE media file from an absolute path'), distinctly identifying the operation. It clearly differentiates from sibling tools like delete_media and apply_subtitles by focusing on ingestion of a file.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is clear: import a single readable media file from an absolute path. It does not explicitly name alternatives or exclusions, but the scope is narrow and well-defined by the input constraints and the unique functionality among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

install_motifA
Destructive

Install a draft. mode 'new' publishes under the draft's own id; 'update' republishes over target_id, or over the target the draft recorded at write_motif_draft { from } when target_id is omitted (refused when it has neither) — bumping the version so every placement re-renders, and rebinding + migrating current-project layers. Returns { motif_id }.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeYes"new" (publish under the draft's own id) or "update" (republish over `target_id`, else the draft's recorded target).
draft_idYesThe draft id (from `write_motif_draft`).
target_idNoFor mode "update": the installed Motif to republish over. Omit to use the target the draft recorded (`write_motif_draft { from }`).

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only destructiveHint=true; the description adds rich behavioral context beyond that: version bumping so every placement re-renders, rebinding and migrating current-project layers, the refusal case, and the `{ motif_id }` return value. This tells the agent what side effects to expect when invoking the tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence with zero filler — every clause earns its place, front-loading the core action before the mode details. It is slightly run-on with nested parentheticals, but appropriately sized for the semantic complexity it conveys.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-param mutation tool with no output schema, the description covers modes, target resolution, failure condition, side effects, and the return shape `{ motif_id }` (needed because no output schema exists). Only minor gaps remain, such as error behavior for invalid draft_id, which are acceptable given the complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The schema already documents mode, draft_id, and target_id semantics thoroughly; the description's added value is the refusal condition and the version-bump effect, which is marginal since the core parameter meaning is already fully in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Install a draft') and precisely distinguishes the two publish modes: 'new' publishes under the draft's own id, 'update' republishes over a target. This clearly separates it from siblings like write_motif_draft (creates drafts) and preview_motif_draft (previews), so an agent can pick the right tool without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains mode selection and target resolution in detail, including the fallback to the draft's recorded `write_motif_draft { from }` target and the refusal condition when neither target exists. It references the draft-producing sibling explicitly, giving clear context, though it stops short of an explicit 'use this instead of X' exclusion statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jump_toA
Destructive

Move the history cursor to an absolute stack index — the history panel's click-a-row, and the way to a state that is neither one undo away nor a checkpoint. index uses project://history's numbering (ops[i] sits at window_start + i; cursor is where you are), so jumping is reading that resource and naming a row; out of range is refused naming the live bounds, and evicted > 0 means index 0 is the oldest SURVIVING state. A revert path like undo/redo/restore_checkpoint, so set_history_lock blocks it. Records nothing; a later edit truncates whatever sat ahead, as after an undo.

ParametersJSON Schema
NameRequiredDescriptionDefault
indexYesAbsolute history index, in `project://history`'s numbering (`window_start + i`).

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotation only says destructiveHint=true, and the description adds substantial behavioral detail: out-of-range indices are refused with live bounds, evicted entries affect the numbering, records nothing, and a later edit truncates future history like undo. This goes far beyond the annotation without contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: purpose first, then parameter semantics, bounds, lock interaction, and side effects. There is no fluff or repetition, and the most important distinguishing facts are front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with no output schema, the description covers what matters for a correct call: what the tool does, how to compute the index, refusal behavior, lock blocking, and post-jump truncation semantics. It is sufficiently complete for an agent to invoke it confidently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though the schema already describes index at 100% coverage, the description enriches it with the exact numbering scheme (`ops[i]` sits at `window_start + i`), the role of `evicted`, and how bounds are computed. This is precisely the kind of semantic context an agent needs to compute a valid index.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Move the history cursor to an absolute stack index.' It also distinguishes itself from undo/redo/restore_checkpoint by describing it as the way to reach a state that is neither one undo away nor a checkpoint, which clearly separates it from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit usage context: the history panel's click-a-row, and the way to jump to an arbitrary state. It names related tools (undo/redo/restore_checkpoint) and an exclusion condition (set_history_lock blocks it), so an agent knows when and when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

launch_weftcutA

Launch the WeftCut desktop app (opens its GUI window on the user’s machine) and wait until its MCP endpoint is reachable. On success the full WeftCut tool catalog becomes available in this session automatically (tools/list_changed). Safe to call when already running — reports that instead of launching twice. Use after weftcut_status says the app is not running.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the behavioral burden; it discloses the GUI side effect, the wait-for-endpoint behavior, automatic catalog availability via tools/list_changed, and idempotency when already running. It does not mention timeout or explicit failure behavior, but the essential behavioral profile is well covered for a 0-parameter launcher.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each carrying distinct useful information: the action and side effect, the success effect, and the invocation condition. The description is front-loaded with the core purpose and contains no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with no output schema and no annotations, the description covers the prerequisite, the side effect, the success behavior, and the already-running case. The only notable omission is failure/timeout behavior, which keeps this just short of fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero parameters, and the description adds no parameter detail because none is needed. Per the rubric, 0 parameters receives a baseline score of 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('Launch') and resource ('WeftCut desktop app'), and clarifies the immediate side effect: it opens the GUI and waits for the MCP endpoint. It is clearly differentiated from sibling tools like weftcut_status by framing the launch as the action to take when the status says the app is not running.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells the agent to call this tool 'after weftcut_status says the app is not running' and explains that calling it when already running is safe and reports instead of double-launching. This is clear selection and precondition guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_checkpointsA
Read-only

List all named checkpoints, oldest first. Returns id, label, actor, created_at per checkpoint (no project snapshot).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds useful context by specifying the ordering (oldest first) and the absence of project snapshot data, which helps set expectations. It does not describe pagination or limits, but with zero parameters and a simple list operation, this is acceptable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence that front-loads the action and scope, then adds the return fields and the key exclusion (no project snapshot). Every word earns its place; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read-only list tool, the description is complete: it states what is returned and what is not. The only minor gap is no mention of pagination or maximum result count, but that is not critical for a checkpoint listing tool with no parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is no schema burden to compensate for. The description fully explains what the tool returns, making parameter semantics a non-issue. Baseline 4 for zero-parameter tools is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists all named checkpoints, oldest first, and specifies the exact fields returned (id, label, actor, created_at). It also explicitly notes that no project snapshot is included, which distinguishes it from related checkpoint tools like restore_checkpoint or create_checkpoint.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this is a read-only listing tool for checkpoints, and the sibling tools include create_checkpoint, restore_checkpoint, and delete_checkpoint, so an agent can infer when to use it. However, it does not explicitly state when not to use it or name an alternative for snapshot-related operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_motifsA
Read-only

List every motif add_motif_layer can place — built-ins plus installed and draft user motifs. Returns [{ id, name, version, size: [w, h], default_duration_s, props_schema, status, content_hash, has_params_ui, target_id? }]; status is builtin | installed | draft. Read props_schema before add_motif_layer — unknown prop keys reject. Drafts are placeable immediately for preview.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Even with readOnlyHint=true, the description adds substantial behavioral detail: the exact returned array shape, the `status` enum values, the optional `target_id` field, and the fact that drafts are immediately placeable. This goes well beyond the annotation and makes the tool's behavior predictable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, each earning its place: scope in the first, return contract in the second, and a downstream usage warning in the third. The most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description fully carries the burden of explaining return values, and it does so with a precise array literal, field names, and enum values. For a zero-parameter read-only tool, nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is nothing for the description to explain about input semantics. Per the 0-parameter baseline this is appropriate, and the description correctly focuses on what the returned data means rather than parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List every motif `add_motif_layer` can place', and disambiguates the scope as 'built-ins plus installed and draft user motifs'. It clearly distinguishes list_motifs from write/install/add sibling operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly tells the agent to read `props_schema` before calling `add_motif_layer` because unknown prop keys reject, which is actionable context for when to consume this tool's output. It does not state when not to use it or name alternative listing tools, but there is no direct sibling that lists motifs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

merge_captionsA
Destructive

Merge two or more captions of ONE caption lane into the earliest, as one recorded edit: its span becomes the union, its text the texts joined by a line break in time order, its style stays; the others are deleted. A gap between them is spanned. Refuses a layer that is not a caption, captions on different lanes, and a union that would overlap another cue of the lane (LayerOverlap). Returns the merged caption's record with removed.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idsYesTwo or more captions on one caption track.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description discloses exactly what happens: the merged edit is recorded, the span becomes the union, the text is joined by line break, other captions are deleted, and gaps are spanned. It also discloses failure modes (`LayerOverlap`) and the return shape. This fully characterizes the destructive behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: the core action is front-loaded, followed by outcome details, refusal conditions, and return value. There is no filler or repetition of the input schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter destructive tool with no output schema, the description is complete. It covers input constraints, merge semantics, deletion behavior, edge cases (gap spanning), error conditions, and the return value. An agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real semantic meaning: it clarifies that the captions must be on one lane, that the earliest becomes the result, and that the union must not overlap another cue. This goes beyond the schema's simple 'Two or more captions on one caption track' without inventing new parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Merge two or more captions of ONE caption lane into the earliest.' It precisely defines the result (span union, joined text, retained style) and distinguishes itself from sibling tools like split_layer and restyle_captions by describing a unique merge behavior. The scope is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states when this tool applies: combining multiple captions on the same caption lane into one. It also gives explicit exclusions by listing refusal conditions (non-caption layers, different lanes, overlapping unions). It does not explicitly name alternatives, but the constraints are specific enough that an agent can select this tool correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_effectA
Idempotent

Reorder an effect within its layer's chain. new_index is 0-based; 0 = first applied. Must be < effect count.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesLayer id.
effect_idYesEffect id.
new_indexYesTarget position in the chain; 0 is applied first.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide idempotentHint=true and destructiveHint=false, so the bar for behavioral disclosure is lower. The description adds meaningful context about new_index being 0-based and bounded, which clarifies valid behavior. It stops short of describing invalid-index handling, but this is minor given the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no redundant wording. The core operation is front-loaded, and the critical index constraint is stated immediately after.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple three-parameter mutation with full schema coverage and annotations covering idempotency and destructiveness, the description provides enough to call the tool correctly. The only missing piece is failure behavior for out-of-range indices, but that is not essential for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds extra meaning to new_index beyond the schema's 'Target position' by specifying 0-based indexing, that 0 is applied first, and that the value must be less than the effect count. This helps an agent compute valid values.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('Reorder') and resource ('effect within its layer's chain'), and distinguishes this from sibling tools like add_effect, update_effect, and delete_effect. The 0-based index semantics also make the purpose actionable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool — when reordering effects in a layer chain — and provides a precondition ('Must be < effect count'), but it does not explicitly state when not to use it or contrast it with alternatives like move_layer or add_effect. Usage is clear enough but not fully guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_layerA
Idempotent

Move a layer to a different track and/or start time. The end time shifts by the same delta. Cross-track moves are validated against the destination's existing layers — overlap rejects with structured options. A start before 0 (for the layer or a link sibling moving with it) is refused, never clamped. Returns the layer's committed envelope, the link siblings that moved with it, and adjusted for any grid snap.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesLayer id.
escape_linkNoAct on this layer alone, leaving its link partners in place. Default false.
new_track_idYesDestination track; the current one to move in time only.
new_t_start_usYesNew timeline start, µs.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the read/destructive hints by disclosing that the end time shifts by the same delta, that cross-track moves are validated against destination layers, that negative starts are refused rather than clamped, and that linked siblings move along unless escape_link is used. It also names the returned data, giving a clear picture of mutation behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is tightly written with four sentences, each carrying substantive information. The primary action is front-loaded, followed by behavioral notes, validation rules, and return values—all without redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with four parameters, no output schema, and modest annotations, this description is exceptionally complete. It covers the operation's effect, validation, edge cases, linked behavior, and return payload, leaving an agent well equipped to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaningful semantics beyond the field names: it explains the relationship between start-time changes and the end time, clarifies cross-track validation behavior, and specifies that out-of-range starts are rejected. This enriches the meaning of new_t_start_us and new_track_id beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource—'Move a layer to a different track and/or start time'—clearly distinguishing this from siblings like move_effect and move_track. The additional detail about end-time shifting and standalone time moves sharpens the boundary further.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The use case is implied well: when you need to reposition a layer in time or across tracks. However, it does not explicitly name alternatives such as shift_layers or set_position, nor does it state when not to use this tool over them. The guidance is inferable but not explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_layers_to_compositionA

Move selected layers into another composition. The anchor lands at anchor_t_start_us; other members retain offsets. Lane assignment is per source track: omit to_track_id to find space, use spawn for fresh lanes, or name a free unlocked lane. Refuses mixed source compositions, locks, cycles, negative starts and membership changes involving retimed Groups. Internal links/transitions move; straddling ones are cut. Markers stay; compositions autofit; Group windows stay fixed.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idsYesThe layers to move; at least one, all in one composition.
to_track_idNoA lane id (locked or occupied REFUSES), "spawn" for a fresh top lane, or omit to bounce to the nearest free lane.
anchor_layer_idYesWhich member `anchor_t_start_us` positions; every other member keeps its offset from it.
anchor_t_start_usYesThe anchor's start time on the DESTINATION's clock — absolute, not a delta.
to_composition_idYesThe destination composition (`project://compositions`). The root is allowed — that is the move back out of a Group.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false from annotations, the description carries real weight: it discloses refusal conditions (mixed source compositions, locks, cycles, negative starts, retimed Group membership changes) and edge-case semantics (internal links/transitions move, straddling ones are cut; markers stay; compositions autofit; Group windows stay fixed). This is exactly the kind of consequence detail annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then layered details in compact sentences with no filler. It is dense but each clause carries behavioral information; slightly telegraphic transitions ('Markers stay; compositions autofit') cost a little readability but no real waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex multi-parameter mutation with no output schema, the description covers destination clock semantics, lane behavior, refusal cases, and post-move side effects. An agent has everything needed to invoke it correctly; nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, but the description adds meaning beyond the schema: it explains that the anchor lands at anchor_t_start_us while other members retain offsets, and that lane assignment is 'per source track.' The omit/spawn/free-lane semantics largely restate the schema's to_track_id description, so it is an enhancement rather than a gap-filler.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource+scope: 'Move selected layers into another composition.' This is clearly distinguishable from the sibling move_layer (single layer) and move_track, and the plural 'layers' plus 'another composition' pins down the operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives precise in-domain routing for lane assignment: omit to_track_id to find space, use 'spawn' for fresh lanes, or name a free unlocked lane, plus a clear refusal list. It stops short of naming an alternative sibling (e.g., move_layer) for single-layer moves, so it misses the explicit when-not comparison that would earn a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_trackA
Idempotent

Move a track to a different z-order position. 0 = bottom of stack. Position must be < current track count.

ParametersJSON Schema
NameRequiredDescriptionDefault
track_idYesTrack id.
new_positionYesTarget index in the stack; 0 is the bottom.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds the boundary constraint 'Position must be < current track count', which is genuinely useful. However, it doesn't disclose what happens when the constraint is violated (error vs clamp vs no-op), and given idempotency, that behavior would matter to the agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler. The primary action is front-loaded, and the z-order zero-point clarification plus boundary constraint each earn their place as operational details the agent needs before calling.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter, non-destructive, idempotent operation with no output schema and no nested objects, the description covers everything an agent needs: what it does, the indexing convention, and the validity bound. The only minor gap is unspecified error behavior on out-of-range input.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters are fully documented in the schema. The description repeats the '0 is the bottom' detail already in the schema and adds the boundary constraint reinforcing new_position. This is marginal added value above the schema, matching the baseline 3 for full coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (move), resource (track), and outcome (different z-order position). The z-order concept distinguishes it from track CRUD siblings like add_track/delete_track/rename_track and from move_effect/move_layer which target other object types. It doesn't explicitly name the closest sibling (restack_layer/set_position), so it's clear but not maximally differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The z-order language implies when to use it (reordering tracks in the stack), but it gives no explicit when-not-to-use guidance and names no alternatives. With siblings like restack_layer and move_layer operating on adjacent concepts, explicit routing would strengthen this. Usage context is inferred, not stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_projectA
Destructive

Open a project folder (the one holding project.json) in the editor, as the start screen's Open does; only one the user asked for. The project open before is saved; its undo history is dropped. Recent projects: read_project { view: "session" }. Returns { name, dir, replaced }.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path of the project folder.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With destructiveHint=true already declared, the description goes well beyond annotations by specifying what gets destroyed ('The project open before is saved; its undo history is dropped') and disclosing the return shape `{ name, dir, replaced }`. It also scopes the target folder precisely via project.json.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, each earning its place: purpose, destructive side effect, alternative lookup, and return shape. Front-loaded with the action and free of filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter mutation tool with no output schema, the description supplies the side effects, the disambiguating folder definition, the sibling lookup path, and the return shape. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter, path, is fully described by the schema ('Absolute path of the project folder'), giving 100% schema coverage. The description adds marginal clarification that the folder is the one holding project.json, but nothing about format or edge cases. Baseline 3 is appropriate when the schema carries the load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Open a project folder (the one holding project.json) in the editor') and ties it to the start screen's Open action, which disambiguates it from create_project and read_project. An agent can tell exactly what this does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'only one the user asked for' gives a clear behavioral constraint on when to invoke, and it routes the agent to `read_project { view: "session" }` for recent projects. It lacks an explicit negative case (e.g., when not to open), but the positive guidance and alternative reference are strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

paste_layersA

Duplicate a set of layers as one recorded edit — the only copy tool. layer_ids[0] is the seed; place its clone with exactly one of t_start_us (absolute) or t_offset_us (relative to the seed's start). Every other clone shifts by the same delta on its source's track; target_track_id moves only the seed's clone. All-or-nothing: a locked or occupied destination for any member rejects the batch (TrackLocked, or LayerOverlap naming the source whose clone would collide). Two or more clones link to each other, never to their sources; pass a single id to copy one linked layer alone. Returns { clones: [{ source, clone }], layers } in input order.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idsYesThe layers to clone; the first is the seed the start time refers to.
t_start_usNoAbsolute start time of the seed's clone; the other clones keep their offsets from it. Mutually exclusive with `t_offset_us`.
t_offset_usNoStart of the seed's clone relative to the seed's own start, so `t_offset_us` shifts every clone by that much. Mutually exclusive with `t_start_us`.
target_track_idNoTrack for the seed's clone. Omit to keep it on the seed's track.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description is exceptionally transparent about behavior: it discloses all-or-nothing batch semantics, the specific error conditions (TrackLocked, LayerOverlap), how clones link to each other rather than to sources, and what the return payload looks like. It also notes this is 'one recorded edit,' implying undoability. This goes far beyond the minimal destructiveHint=false annotation and adds real behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place; there is no filler or repetition of the schema. It front-loads the core purpose and uniqueness before diving into parameter semantics and error behavior. The structure moves logically from what the tool does, to how to use it, to edge cases and return value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema and only minimal annotations, the description covers everything an agent needs to invoke and interpret the tool: parameter relationships, batch atomicity, failure modes, linking behavior, and the return structure. This is a complex tool with four interacting parameters, and the description is complete enough that no critical behavioral question is left unanswered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, but the description adds significant semantic value beyond the schema. It explains that layer_ids[0] is the seed, that t_offset_us shifts every clone by the same delta, that t_start_us is absolute for the seed's clone, and that target_track_id affects only the seed's clone. These relationships are not inferable from the schema definitions alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Duplicate a set of layers as one recorded edit.' It also explicitly claims to be 'the only copy tool,' which clearly distinguishes it from sibling layer operations like move_layer, update_layer, or delete_layers. An agent can immediately understand what this tool does and why it is unique.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives strong usage guidance: the seed layer is identified, the caller must choose exactly one of t_start_us or t_offset_us, and target_track_id semantics are clarified. It also explains the single-id path for copying one linked layer alone, which effectively tells the agent when a simpler invocation is appropriate. The phrase 'the only copy tool' provides clear differentiation from alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pingA
Read-only

Liveness check. Returns 'pong' to confirm the WeftCut MCP server is reachable.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description adds the precise return value ('pong'). This is sufficient for a tool with no parameters and no side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with no filler. The core purpose and expected response are front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless liveness check with no output schema, the description fully covers what an agent needs to know: what it does, what it returns, and why it exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there are no semantics to clarify. The baseline of 4 applies because the description needs to compensate for nothing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific purpose: a liveness check that returns 'pong' to confirm server reachability. It is unambiguous and distinct from all sibling tools, which perform media or project operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool: whenever confirmation of server reachability is needed. It doesn't explicitly exclude alternatives, but no alternative liveness check exists among the siblings, so the usage context is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

preview_motif_draftA
Read-only

Render one frame of a Motif (draft / installed / built-in) as a base64 PNG, so you can SEE your output and self-correct. id, t_sec (content time); optional props (default: the manifest defaults) and width/height (default: the motif's own size). Needs the app's preview runtime; errors rather than hangs when it is not ready.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMotif id (draft / installed / built-in).
propsNoProps; omitted or `{}` uses the manifest defaults.
t_secYesContent time in seconds to render (0 = first frame).
widthNoRender width; default the motif's manifest width.
heightNoRender height; default the motif's manifest height.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint=true already covers safety, and the description adds useful non-obvious behavior: it errors rather than hangs when the preview runtime is unavailable and clarifies the output is a base64 PNG. This is meaningful context beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences with the primary purpose front-loaded and parameter/default/clarification details following. No filler or redundant phrasing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema, the description supplies the essential result format (base64 PNG), the required inputs, the optional inputs with defaults, the prerequisite runtime, and the failure mode. An agent has enough to invoke it correctly without opening the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents id, t_sec, props, width, and height. The description mostly restates those defaults ('props (default: the manifest defaults)', 'width/height (default: the motif's own size)') without adding new semantic information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair: 'Render one frame of a Motif' and specifies the exact output format (base64 PNG). It also scopes the id to 'draft / installed / built-in', which separates it from write/edit tools in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly states the intended use ('so you can SEE your output and self-correct') and gives a precondition ('Needs the app's preview runtime'). It does not enumerate alternatives or explicit when-not-to-use cases, so it misses the top tier by a narrow margin.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_projectA
Read-only

Read project state as a tool result — the same views the project://* resources serve, for a client that cannot read MCP resources. view: current, composition, compositions, media, tracks (layer envelopes), layer (needs id), markers, links, transitions, settings (preferences + metadata incl. modified_at), history, session (who holds the work session), effects (the effects catalog), media_thumbnail / media_frame (an IMAGE block; id is the media id, media_frame also takes t_us). composition, tracks, markers, links, transitions take composition_id for a Group's, the root when omitted. JSON views return the body as text.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoThe layer id for view `layer`; the media id for `media_thumbnail` / `media_frame`.
t_usNoFor `media_frame`: the frame time in the SOURCE, µs.
viewYesWhich view to read.
composition_idNoFor the per-composition views: a Group's composition; omit for the root.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the readOnlyHint annotation by disclosing output formats (IMAGE blocks for media_thumbnail/media_frame, text body for JSON views) and parameter dependencies (layer needs id, media_frame takes t_us, composition_id applies to specific views). This gives the agent a complete behavioral model of what to expect.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place. It front-loads the purpose and usage context, then systematically lists views and their parameter requirements, and finishes with output format. No redundant words or tautologies.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 15 views, 4 parameters, and no output schema, the description covers all necessary ground: purpose, when to use, parameter interplay, and output types. An agent can confidently invoke any view without ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema descriptions already cover 100% of parameters, the description adds cross-referential semantics not in the schema: it maps each view to the parameters it requires, explains which views accept composition_id, and clarifies that media_frame also takes t_us. This is substantive added value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Read'), resource ('project state'), and purpose ('the same views the project://* resources serve, for a client that cannot read MCP resources'). It enumerates all supported views, making it unmistakably distinct from any sibling tool, none of which perform project state reads.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly specifies when to use this tool: when the client cannot read MCP resources, and it clarifies that it mirrors the project://* resources. This gives the agent a clear condition for selection over alternative approaches, effectively ruling out the resource-based path.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

redoA
Destructive

Redo the next edit. Errors with NothingToRedo if no redo is available. A new commit truncates the redo tail. Answers redone: the op reapplied.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes beyond the destructiveHint=true annotation by disclosing the failure mode (NothingToRedo), the state-invalidation rule (a new commit truncates the redo tail), and the return key `redone`. This is meaningful behavioral context an agent could not derive from the annotation alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the action, then the error case, then the state rule and result key. Every sentence carries distinct information with zero filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, no-output-schema tool with a destructive annotation, the description covers the action, error, state semantics, and return key. The one remaining gap is not naming the undo/redo relationship explicitly, but the definition is otherwise complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters (empty schema, 100% coverage), so there is nothing for the description to document. Baseline 4 applies per the rules.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Redo the next edit.' This is unambiguous and self-evidently the inverse of the sibling 'undo'. It does not explicitly name or route against a sibling, but the operation is clear without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied (invoke to reapply an undone edit) and the NothingToRedo error hints at the precondition. However, there is no explicit when-to-use statement or reference to the 'undo' alternative that would make the pairing fully unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_pausesA
Destructive

Remove detected pauses and ripple downstream clips as one edit. Audio or VideoClip with linked audio. Defaults match detect_pauses; pad_us keeps 100000 µs on each side, while edge pauses trim entirely. Link members are cut together. Returns surviving_layer_ids, removed and removed_us. Refuses locks, ripple collisions, straddling links and an entirely silent clip. Review with detect_pauses and anchored markers first.

ParametersJSON Schema
NameRequiredDescriptionDefault
pad_usNoMicroseconds of each pause KEPT on each side. Default 100000; 0 erases each pause whole. Must satisfy 2 * pad_us < min_pause_us.
layer_idYesTarget Audio layer id, or a VideoClip id that delegates to its linked Audio layer.
min_pause_usNoShortest pause worth removing, in microseconds — the same parameter `detect_pauses` takes. Omit to use that tool's own default.
threshold_ampNoPeak amplitude threshold in [0.0, 1.0], the same parameter `detect_pauses` takes. Omit to use that tool's own default.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations supply only destructiveHint=true; the description adds substantial context beyond that: ripple propagation downstream, link members being cut together, default pad behavior matching detect_pauses, edge-pause full trimming, and a complete refusal taxonomy. It also names the return fields, which matters because no output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the verb and effect, and nearly every clause carries information (defaults, link behavior, return values, refusals). It is dense but not padded; a slightly clearer separation of the review guidance from the parameter notes would help readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with no output schema, the description covers the missing pieces: ripple behavior, link coupling, refusal conditions, and the three return fields. An agent has enough to call it correctly and interpret the result without further documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already carries the parameter burden, making 3 the baseline. The description adds marginal value by tying defaults to detect_pauses and clarifying that edge pauses trim entirely, but it does not deepen the semantics of threshold_amp or min_pause_us beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Remove detected pauses') plus the key side effect ('ripple downstream clips as one edit'). It explicitly positions itself against the sibling detect_pauses, so an agent can separate the analysis tool from the mutation tool without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly routes the agent through the read-first workflow ('Review with detect_pauses and anchored markers first') and enumerates refusal conditions (locks, ripple collisions, straddling links, silent clip) that tell the agent when the call will fail. No explicit statement of when a different edit tool (e.g. ripple_delete_gap) would be preferable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rename_compositionA
Idempotent

Name a Group's composition (label: null or blank clears it back to the derived name). Recorded, so undo reverts it. The root composition refuses (RootComposition): it has no name — it is the timeline. Composition ids: project://compositions.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelNoThe new name; null or blank clears it.
composition_idYesComposition id.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint and destructiveHint false. The description adds behavioral context beyond this: the operation is recorded so undo reverts it, and the root composition will refuse. This helps the agent predict side effects without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, each carrying essential information: the core action, label clearing behavior, undo semantics, root exception, and id format. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter mutation with annotations covering safety and a simple, well-described operation, the description is complete. It covers what happens on clear, the undo behavior, the root refusal, and the id namespace. No output schema exists for a simple rename, so return value details are not required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value by explaining that null/blank returns the name to the derived name and by specifying composition id format (`project://compositions`), going beyond the minimal schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Name a Group's composition') and resource, and clarifies behavior for null/blank labels and the root composition. This clearly distinguishes the tool's purpose from the many sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool: to set or clear a composition's name. It explicitly notes that the root composition refuses, providing a when-not case. It does not explicitly compare against sibling alternatives like update_composition, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rename_trackB
Idempotent

Name a track, reserved A roll / B roll / audio / caption tracks included. Recorded. label: null (or blank) clears it back to the derived name — its role, or its position in the stack.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelNoThe new name. null or blank clears it back to the displayed-by-default name.
track_idYesTrack id.

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, and the description adds useful context on top of them: reserved tracks are included, the operation is recorded, and a null/blank label clears the name back to the derived default. The standalone sentence 'Recorded.' is vague, but it still discloses behavior beyond the schema and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core action, but the sentence fragment 'Recorded.' is abrupt and cryptic. The structure is concise almost to the point of telegraphic, so it is serviceable but not polished.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter, idempotent, non-destructive tool with full parameter documentation and no output schema, the description covers the important semantics well: rename scope, null/blank reset behavior, and recorded status. The main completeness gap is clarifying what 'Recorded.' actually means, but the agent has enough to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters, including the null-clears behavior. The description adds only a small detail about what the derived name means ('its role, or its position in the stack'), which is mild extra context rather than significant compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Name a track') and a clear resource ('track'), and it extends the scope to reserved A/B roll/audio/caption tracks. It does not explicitly differentiate from sibling track operations, but the core action is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance about when to use this tool versus alternatives like set_track_flags or add_track, and no exclusions or preferred contexts are given. The only usage signal is the implied 'use this to name a track' meaning.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

restack_layerA
Idempotent

Restack a visual layer above/below a stable layer or track anchor. Supply exactly one anchor; track anchors work through gaps. A sole occupant carries its track; shared or reserved sources split onto a fresh track. Reserved tracks stay put. Audio, cross-composition and self-anchors reject. Already in place records nothing. One undo step.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesThe visual layer to restack.
positionYesPlace the layer directly above or directly below the anchor layer's track.
anchor_layer_idNoThe visual layer to place it against; supply exactly one of anchor_layer_id / anchor_track_id.
anchor_track_idNoA visual track to place it against, including an empty reserved lane. Supply instead of anchor_layer_id.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With idempotentHint and destructiveHint already declared, the description adds real value: 'Already in place records nothing' reinforces idempotency, 'One undo step' discloses undo semantics, and it enumerates rejection cases and track-splitting behavior. Missing only auth/permission context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely dense and front-loaded: the core action leads, followed by tightly-claused constraints. Every sentence carries a discrete rule (anchors, splitting, reserved tracks, rejections, no-op, undo) with zero filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists and annotations only cover idempotency/safety, so the description bears the burden and mostly meets it by covering rejections, no-op behavior, splitting, and undo. It stops short of explaining return values or error surfacing, leaving a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds behavioral meaning: it clarifies the exactly-one-anchor rule, that track anchors work through gaps, and how sole vs shared/reserved sources affect the anchor's own track. This goes beyond the raw field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb (restack) and resource (visual layer) with an explicit positional relationship (above/below). It is not a tautology, though it does not directly name sibling alternatives like move_layer to disambiguate further.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states hard preconditions and rejections ('supply exactly one anchor', audio/cross-composition/self-anchors reject), which guides usage, but never says when to choose this over move_layer, shift_layers, or set_position. Usage is implied through constraints rather than explicit routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

restore_checkpointA
Destructive

Restore a named checkpoint. Records a new history entry — undo will return to the pre-restore state. Errors with CheckpointNotFound if the id doesn't exist. The agent panel preserves activity and inserts a restore boundary; only edits with known history provenance are marked reverted.

ParametersJSON Schema
NameRequiredDescriptionDefault
checkpoint_idYesCheckpoint id.

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the destructiveHint annotation by explaining that a new history entry is recorded, that undo will return to the pre-restore state, that CheckpointNotFound is raised for unknown ids, and that the agent panel inserts a restore boundary with provenance-dependent revert marking. This is rich, non-obvious behavioral detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences deliver the core action, undo interaction, error condition, and panel behavior without padding. The first sentence front-loads the primary purpose, and the additional sentences each contribute distinct behavioral information, though the final clause is somewhat dense.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with a destructiveHint annotation and no output schema, the description covers the main invocation need: the input id, the error case, and the side-effect relationship with undo. It stops short of describing the success return value or how checkpoint ids are obtained, but these are minor given the sibling list_checkpoints tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with checkpoint_id described as 'Checkpoint id.' in the schema. The description reinforces that this is a named checkpoint and mentions the 'id doesn't exist' error, but it does not add meaningful parameter-level details such as format, source, or constraints beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Restore a named checkpoint', a clear verb+resource pairing that immediately identifies the action and object. It distinguishes itself from sibling tools like create_checkpoint, delete_checkpoint, and list_checkpoints by focusing specifically on restoring to a previously saved state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly establishes the context for use: restoring a named checkpoint by its id, with explicit error behavior if the id is invalid. It does not explicitly name alternatives or exclusions, but the purpose and the relationship to undo are evident enough to guide selection among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

restyle_captionsA
Idempotent

Restyle the captions in one recorded edit — EVERY Text layer on every caption-role track in every composition, so multiplied caption lanes stay one look, or only layer_ids (each must be a caption). Omitted or null fields are left alone. outline_width: 0 removes the outline; a positive width adds or resizes one (keeping its colour, black if it had none). Sizes are composition px. A Text layer from add_text_layer is not a caption — style it with update_layer_params.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorNoText colour.
layer_idsNoOnly these captions. Omit for every caption in the project.
font_familyNoFont family for every caption.
font_size_pxNoFont size, composition px.
outline_widthNo0 removes the outline; a positive width (composition px) adds or resizes it.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the idempotentHint and non-destructive annotations, the description adds meaningful behavioral detail: omitted or null fields are left untouched, outline_width 0 removes the outline while positive widths add/resize, and sizes are in composition pixels. It also calls out an important community nuance — add_text_layer text layers are not captions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than a minimal two-liner, but each clause earns its place: scope, layer restriction, idempotent field behavior, outline behavior, units, and the alternative tool. The aside 'so multiplied caption lanes stay one look' is somewhat explanatory, but it clarifies intent without bloating the core instruction.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema, the description covers what an agent needs to invoke it correctly: full scope semantics, parameter units, special values, idempotence, and the main false-positive case. Nothing required for a correct call is left out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds real semantics beyond the schema: partial-update behavior for omitted/null fields, the special outline_width 0 sentinel, units for font_size_px and outline_width, and the requirement that layer_ids entries must be captions. This far exceeds the baseline baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific action and resource: restyle captions. It then defines the exact scope — every Text layer on every caption-role track in every composition, or a restricted set via layer_ids — and ends by distinguishing captions from add_text_layer text, so the agent can tell it apart from update_layer_params.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly explains when to use this tool versus an alternative: apply to all captions project-wide, restrict to layer_ids, or style non-caption text with update_layer_params. The final sentence is a clear when-not/alternative statement rather than leaving the choice implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

retime_layersA
Idempotent

Retime exactly the selected clips, keeping their starts and source windows. Atomic; rejects collisions, illegal transitions and nested targets. Rate is absolute, positive and rational. Duration is in microseconds. Returns actual rates after grid snapping. Links do not expand the selection.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetYesAbsolute rate or duration.
layer_idsYesExplicit target clips

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations only covering idempotence and non-destructiveness, the description adds substantial behavior: atomicity, rejection of collisions/illegal transitions/nested targets, absolute-positive-rational rate semantics, microsecond duration units, and post-grid-snap returned rates. These are exactly the traits an agent needs before invoking and are not contradicted by the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose in the first clause, then packs invariants, failure modes, units, and return behavior into tight telegraphic sentences. No filler; every clause carries semantic weight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-param tool with no output schema, the description covers atomicity, failure modes, and return semantics (actual rates after snapping). The one gap is that 'grid snapping' is referenced without explaining the grid, and empty-selection behavior is unstated, so it is strong but not exhaustive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both target union variants and the num/den rational. The description's 'Rate is absolute, positive and rational' and 'Duration is in microseconds' largely restate what the schema ('Reduced positive rational', 'Target microseconds', 'Absolute rate or duration') already provides, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (retime selected clips) plus the key invariant it preserves (starts and source windows), which cleanly separates it from siblings like shift_layers, trim_layer, and split_layer. An agent can identify the operation without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: 'Retime exactly the selected clips' and 'Links do not expand the selection' bound the scope, but no alternatives (e.g., shift_layers for moving without retiming) or when-not conditions are named. Adequate context, no explicit routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ripple_delete_gapA
Destructive

Close a GAP — an empty span on one track between two layer boundaries — so everything after it moves left and the film gets shorter; nothing is deleted. [start_us, end_us) must be the whole gap as it is now: end_us exactly where a layer on track_id starts, start_us exactly where one ends (or 0 before the first clip); the space after the last clip is not a gap. Otherwise GapNotFound carries the span you sent — re-read project://tracks and retry. The closing is delete_layers { ripple: true }'s: every layer starting at or after end_us on every track shifts left, anchored markers follow, free markers and the playhead stay. Refuses whole with the same names — RippleInsideHole (a layer on another track starts inside the gap: delete it first), RippleCollision, RippleLinkStraddles, RippleLockedLayer / TrackLocked (a gap on a locked lane always refuses). One recorded edit.

ParametersJSON Schema
NameRequiredDescriptionDefault
end_usYesGap end (exclusive), timeline, µs.
start_usYesGap start, timeline, µs.
track_idYesThe track the gap is on.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description details the exact ripple mechanics: which layers shift, anchored versus free markers, playhead behavior, and that the operation is one recorded edit. It also names all refusal reasons and their triggering conditions. The 'nothing is deleted' phrasing refers to layers/clips and does not contradict destructiveHint, since removing the gap is still a timeline-destructive edit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded with the core behavior, then organized into preconditions, error handling, and side effects. There is little fluff, though the phrasing 'Refuses whole with the same names' is awkward and the long single paragraph could be improved with structured bullets.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex ripple operation with sparse annotations and no output schema, the description covers input validity, ripple effects across tracks, marker/playhead behavior, error names and recovery advice, and undoability. It is slightly incomplete in that it never states what a successful call returns or gives an explicit alternative for simply shifting layers without closing a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds essential meaning beyond the schema: the exclusive/inclusive boundary requirements, the special case of 0 before the first clip, and the condition that the space after the last clip is not a gap. This materially clarifies how to compute track_id, start_us, and end_us correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Close a GAP' and defines it as an empty span between layer boundaries. It then states the ripple behavior ('everything after it moves left and the film gets shorter') and explicitly distinguishes the operation from deletion ('nothing is deleted'), which helps separate it from sibling delete_layers.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly enumerates valid-use preconditions: start_us/end_us must match the whole gap exactly, and the space after the last clip is not a gap. It also tells the agent what to do when GapNotFound occurs. However, it does not explicitly name an alternative sibling tool or provide a when-to-use-versus-alternative comparison.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

separate_audio_to_new_trackA

Lift an Audio layer onto a new track of its own, in the source lane's slot, and return the new track's record with the layer's. The layer is untouched — id, span, gain, role and links survive — so an auto-paired dialogue clip gets its own lane while the pair still moves together; delete_link afterwards to make them independent. WrongLayerKind on anything but an Audio layer (a VideoClip's sound is the Audio layer linked to it — see project://tracks). A source lane the lift emptied is pruned. One undo reverts it.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesThe VideoClip whose audio splits off onto its own layer.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say destructiveHint=false, so the description carries the burden and fully delivers: layer untouched, id/span/gain/role/links preserved, empty source lane pruned, and single undo. It also reveals the error condition (WrongLayerKind) and return value shape. This goes well beyond annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Five short, information-dense sentences, each adding a distinct fact: outcome, preservation/link behavior, error case, pruning side effect, and undo. Front-loaded with the primary result. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given moderate complexity and no output schema, it explains the return (new track's record with the layer's), the input contract, side effects, and rollback. The only item left implicit is the exact record shape, which is appropriate without an output schema. No significant gap for selecting and invoking correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description does add useful clarification that layer_id must be an Audio layer and how to locate it from a VideoClip. However, the schema's own parameter description calls it 'The VideoClip whose audio splits off,' which conflicts with the tool description's 'anything but an Audio layer' rule, leaving ambiguity for an agent. Hence 3, not higher.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Uses a specific verb ('Lift') and resource ('Audio layer'), and immediately states the outcome: new track in the source lane's slot, returning both records. This is distinct from siblings like split_layer or move_layer because it targets only Audio layers and creates a dedicated track. The only small gap is that it doesn't name a sibling it is not, but the behavior is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly frames the use case (auto-paired dialogue clip gets its own lane) and instructs to call delete_link afterwards to break the pair. It also defines the accepted layer kind and warns about WrongLayerKind, including where to find an Audio layer for a VideoClip. It stops short of explicitly listing alternative tools or when-not-to-use conditions, so not a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_extrapolationA
Idempotent

Set what a keyframed track does outside its keys: before the first and/or after the last (at least one; the other keeps its value). "Hold" (the end value, default), "Loop" (repeat from the first key — a visible jump when first ≠ last), "PingPong" (alternate cycles run backwards), "Offset" (each cycle adds the last-minus-first delta), "Continue" (carry the last segment's end velocity on as a line). The period is last.t − first.t; a single-key track never extrapolates. Refused on a Static track. For path_progress, only Hold / Loop / PingPong are supported. Reads back as extrapolate on get_param_track.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoAfter the last key; modes as described by this tool.
beforeNoBefore the first key; modes as described by this tool.
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare idempotence and non-destructiveness; the description adds substantial behavioral context beyond them: the default is Hold, the meaning of each mode's cycle behavior, the period definition (last.t − first.t), explicit refusal on Static tracks, and the path_progress restriction. This is exactly the kind of context annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action in the first clause, then enumerates modes. Dense with parenthetical asides, but each sentence carries genuine information (defaults, jump behavior, single-key rule, refusal). Slightly heavy but no wasted filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-param mutation with no output schema, the description covers mode semantics, defaults, edge cases (single key, Static track), per-parameter restrictions, and how the value reads back via get_param_track. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the schema enum descriptions explicitly defer to this tool ('modes as described by this tool'), so the description is the authoritative source defining Hold/Loop/PingPong/Offset/Continue. It also clarifies the before/after relationship ('at least one; the other keeps its value'), adding meaning the schema does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Set') and the resource precisely ('what a keyframed track does outside its keys'), i.e., extrapolation behavior. An agent can immediately distinguish this from siblings like set_keyframe, set_param_track, or get_param_track.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete constraints on when the tool applies: 'Refused on a Static track', single-key tracks never extrapolate, and for path_progress only Hold/Loop/PingPong are supported, plus 'at least one' of before/after required. It routes the read-back to get_param_track. It stops short of naming alternative tools for other scenarios but the applicability conditions are explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_frame_interpolationC
Idempotent

Choose temporal frame interpolation. Only FrameSampling is available; other modes are refused.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idsYesVisual clips
interpolationYesSampling configuration.

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare idempotentHint=true and destructiveHint=false, indicating safe, repeatable operations. The description adds that only 'FrameSampling' is available and other modes are refused, which is useful behavioral context about constraints. However, it doesn't explain why other modes are refused or what happens to existing interpolation settings when a new one is applied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly focused sentences with no wasted words. The purpose is front-loaded, followed immediately by the key constraint. Efficient and clear structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-parameter tool with 100% schema coverage and annotations covering safety profile, the description provides adequate coverage. The critical gap is the lack of connection to sibling tools like get_frame_interpolation_capabilities that would help an agent understand the broader workflow context. The nested object structure for interpolation is not elaborated beyond what the schema provides.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema fully documents both parameters. The description adds constraint information about which enum values are accepted ('Only FrameSampling is available'), which is meaningful parameter insight beyond the schema. However, it doesn't explain what 'layer_ids' should target or how interpolation interacts with specific layers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Choose temporal frame interpolation') and identifies the setting being manipulated. However, it doesn't distinguish this tool from related siblings like get_frame_interpolation_capabilities or retime_layers, leaving ambiguity about when to use this specific function versus related interpolation operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. With a sibling tool 'get_frame_interpolation_capabilities' that clearly provides capability information, an agent would benefit from understanding that this tool sets the mode while the sibling queries capabilities. No exclusions or prerequisites are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_history_lockA
Idempotent

Block reverts (undo / redo / jump_to / restore_checkpoint) while a batch runs, or release the block. locked: true needs a reason, shown beside the lock badge in the agent and history panels and returned to any revert attempt; locked: false takes none and is idempotent. Never affects what records: the lock rejects reverts, it does not fold a batch into one history entry. Last writer wins. Always pair the lock with its release: ending the work session that OWNS it releases it, as does that connection going away; a lock taken outside a work session is released only by locked: false (from any connection) or by the user, and switching views never releases one. Unrecorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
lockedYestrue blocks reverts; false releases the block.
reasonNoWhy the history is locked — required when locking, refused when unlocking.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the idempotentHint and destructiveHint annotations, the description exposes important traits: 'Last writer wins', session ownership auto-release, connection-loss release, the non-release on view switches, and the fact that locks taken outside a work session require explicit unlocking. It also notes that the reason is surfaced to revert attempts, which helps agents anticipate observable behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence carries meaningful operational guidance: core behavior, reason semantics, record-scope boundary, last-writer-wins, lifecycle rules, and non-recording. The content is front-loaded and dense without filler, and the edge cases are worth the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter lock tool with no output schema and meaningful lifecycle side effects, the description is complete: it covers both parameter states, release paths, ownership behavior, and what the lock does not do. An agent has enough context to invoke it correctly and avoid common misuse.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already covers both parameters at 100%, including the conditional requirement on reason. The description adds value by explaining the conditional contract in plain terms, noting that locked: false rejects a reason, and clarifying that the reason is displayed and returned to revert attempts. This goes beyond the schema's property descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action pair: block or release history reverts, naming the exact operations affected (undo / redo / jump_to / restore_checkpoint). It distinguishes itself from history-manipulation siblings by clarifying that it only rejects reverts and does not alter what records, so an agent cannot confuse it with checkpoint tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states when to use it ('while a batch runs'), when to release, and the lifetime rules tied to work sessions/connections. It also gives a firm when-not via 'Never affects what records', but it does not explicitly name an alternative tool for folding history entries, so it stops short of full explicit alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_keyframeA
Idempotent

Insert or update a keyframe on a layer param; t_us is timeline-absolute. A Static track is lifted to Keyframed; a key at the same frame is updated in place. Returns the key (keyframe_id, t_us). value is typed by param_key: a number for scalars, {r,g,b,a} (0..255) for "color"; an effect param must sit in its catalogued range (effects://catalog). interp (optional) eases the segment LEAVING this key (Hold | Linear | Bezier {p1,p2} | Elastic | Bounce); omitted, it inherits the preceding segment's. A Bezier on the LAST key is refused — its p2 lands on the next key, so add that key first. One side, the continuity or a preset: update_keyframe; Auto tangents: smooth_keyframes.

ParametersJSON Schema
NameRequiredDescriptionDefault
t_usYesKey time, timeline-absolute, µs.
valueYesTyped by `param_key`: a number for scalar params (x, y, path_progress, scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity, gain_db, pan, effect params), {r,g,b,a} (0..255) for "color". Path mode takes path_progress (a fraction) instead of x/y.
interpNoEasing: {"kind":"Hold"} | {"kind":"Linear"} | {"kind":"Bezier","p1":[x,y],"p2":[x,y]} | {"kind":"Elastic","dir",amplitude?,period?} | {"kind":"Bounce","dir"}.
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare idempotentHint/destructiveHint; the description adds the real behavioral context: a Static track is lifted to Keyframed, a same-frame key is updated in place (explaining the idempotency), the return shape (keyframe_id, t_us), interp inheritance from the preceding segment, and the Bezier-on-last-key refusal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and packs typing, constraints, and alternative routing into a few dense clauses; every sentence carries information. It is information-rich rather than padded, though the density is at the upper end for a single description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers typing, the mutation side effect, constraints, return shape (compensating for the absent output schema), and sibling routing, which is thorough for a 5-param nested tool. Missing only peripheral detail such as permission/authorization requirements.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema lacks: value typing by param_key, the catalogued range requirement for effect params, and the rule that omitted interp inherits the preceding segment's easing. These go beyond the schema's field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Insert or update a keyframe on a layer param') and immediately scopes it ('t_us is timeline-absolute'). It distinguishes itself from the cluster of keyframe siblings by naming update_keyframe and smooth_keyframes as the alternatives for their respective cases.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: use update_keyframe for 'one side, the continuity or a preset', and smooth_keyframes for 'Auto tangents'. It also gives a hard when-not ('A Bezier on the LAST key is refused'), telling the agent to add the next key first.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_layers_enabledA
Idempotent

Set enabled on exactly these layers in one recorded edit — the only tool that writes it, for one layer or many. Nothing is expanded: to hide a linked A/V pair, pass both members. A locked layer (LayerLocked) or owning track (TrackLocked) rejects the whole batch. Unlock before editing.

ParametersJSON Schema
NameRequiredDescriptionDefault
enabledYestrue shows, false hides — preview and export alike.
layer_idsYesThe layers to show or hide.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the idempotent/non-destructive annotations: it discloses that the change is a single recorded edit (undo-relevant), that it is atomic ('rejects the whole batch'), and that no expansion occurs for linked A/V pairs. These are non-obvious behaviors an agent must know before calling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action, then constraints. Every clause carries distinct, actionable information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema is needed for a setter, and annotations only cover idempotency/safety; the description fills the remaining gaps (atomicity, locking, no auto-expansion, undo scope). An agent has everything required to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real semantics: 'enabled' acts on preview and export alike, and 'layer_ids' must include both members of a linked A/V pair rather than expanding. This meaningfully enriches otherwise terse parameter docs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('Set `enabled` on exactly these layers') with explicit scope ('for one layer or many'). Crucially it distinguishes itself from siblings by claiming 'the only tool that writes it', so an agent can route correctly without comparing schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear when-to-use context and an essential precondition ('Unlock before editing'), plus the failure condition for locked layers/tracks. No alternative tool is named, but the description asserts none exists, which is the meaningful routing fact here.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_marker_anchorA
Idempotent

Tie a marker to a clip so the mark FOLLOWS it through moves, trims, splits and composition crossings, or cut it loose with layer_id: null. layer_id must be a clip of the marker's own composition. Tying names the source instant the mark already sits on, so nothing moves; t_us stays the field to read. Refuses without writing: a layer in another composition (CrossCompositionSet), a kind with no source window such as Color or Text (WrongLayerKind), a marker outside the clip's span (InvalidArgument — update_marker it onto the clip first). Re-tying replaces the tie. Untying keeps the frame currently shown and is the one exit from hibernating; untying a free marker records nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesThe clip to follow, or null to cut the marker loose.
marker_idYesMarker id.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the idempotentHint and destructiveHint annotations, it explains the non-moving nature of tying, that re-tying replaces the tie, that untying keeps the currently shown frame, and that untying a free marker records nothing. The named exception types give the agent concrete expectations about failure modes without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core operation and then layers constraints, errors, and edge cases in a logical order. Every sentence carries distinct information, from null behavior to re-tying to hibernating, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with two simple parameters, no output schema, and moderate operational complexity, this description is remarkably complete. It covers the main success path, failure modes, the alternative tool, idempotent re-tying, untying behavior, and the special 'hibernating' case, so an agent has enough context to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds valuable semantics for `layer_id`: it must be a clip of the marker's own compositionchers, and it clarifies that `t_us` remains the field to read. This goes beyond the schema's simple 'clip to follow' explanation, though `marker_id` itself receives no extra detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence defines a specific action ('Tie a marker to a clip') and clearly contrasts it with the reverse ('cut it loose with layer_id: null'), so an agent immediately knows what the tool does. It also distinguishes itself from marker editing by pointing to `update_marker` for the 'marker outside the clip's span' case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use behavior (tying and untying), explicit refusal conditions (CrossCompositionSet, WrongLayerKind, InvalidArgument), and an explicit alternative: `update_marker` it onto the clip first. The note that untying is 'the one exit from hibernating' adds a specific use-case trigger.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_param_trackA

Replace a whole animation track in one undo step. Static: {mode:'Static',value:v}. Keyframed: {mode:'Keyframed',value:[{t_us,value,...}],extrapolate?}. Key times are timeline-absolute; retain time_fraction on retimed keys. IDs are generated; omit id (including on copied read records). Keys default to Linear, identity Free tangents and Broken continuity; optional in/out/segment/continuity author custom curves. Extrapolate defaults to Hold/Hold. Auto/Smooth tangents are solved on write. Returns the committed keys with generated IDs and snapped times. For individual changes use set_keyframe/update_keyframe.

ParametersJSON Schema
NameRequiredDescriptionDefault
trackYesAn animation track: {"mode":"Static","value":v} or {"mode":"Keyframed","value":[keyframes],"extrapolate":{before, after}} (Hold/Hold when omitted). Values are typed by `param_key` — a number, or {r,g,b,a} (integers 0..255) for "color".
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description carries most of the burden and delivers: the single-undo-step semantics of a whole-track replacement, all defaults (Linear segments, identity Free tangents, Broken continuity, Hold/Hold extrapolation), that Auto/Smooth tangents are re-solved on write, that IDs are generated and must be omitted, and that key times are timeline-absolute. This is exactly the mutation-specific context the thin annotation does not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then format, defaults, return value, and sibling routing in a tight block with no filler sentences. It is dense and slightly run-on, but every sentence carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a deeply nested 3-parameter schema, no output schema, and minimal annotations, the description covers the contract adequately: input shapes, defaults, ID/time handling, and the return value ('the committed keys with generated IDs and snapped times'). Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds operational meaning beyond the schema: the Static vs Keyframed value shapes, that time_fraction must be retained on retimed keys, that ids should be omitted (including on copied read records), and that key times are absolute here versus layer-local in set_position. It synthesizes rather than merely restating.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource ('Replace a whole animation track') plus a behavioral qualifier ('in one undo step'), and explicitly distinguishes itself from the sibling tools set_keyframe/update_keyframe that handle individual changes. An agent can route correctly without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The final sentence names the alternative tools and the condition that selects them ('For individual changes use set_keyframe/update_keyframe'), giving clear routing context. It stops short of a full when/when-not treatment (e.g. relationship to set_position, clear_keyframes, or set_extrapolation is unstated), so it is strong but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_positionA

Replace a layer's position outright: XY tracks, or a motion path with a scalar progress track. Times are layer-local µs. Existing XY animation is replaced only by this explicit call. IDs are generated; omit all node/key ids. Keys need only t_us/value (Linear, identity tangents); nodes need only point (Line, Corner, zero handles). One undo step.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesLayer id.
positionYesXY: `x`/`y` tracks in composition px. Path: `path.nodes` plus a `progress` track, 0..1 = distance along the path (Hold/Loop/PingPong extrapolation only).

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide destructiveHint=false, so the description carries most of the burden. It discloses important behavior: 'Existing XY animation is replaced only by this explicit call' and 'One undo step.' These details go beyond the annotation and help the agent understand the mutation and reversibility. Permissions or auth needs are not mentioned, but no annotation covers that either.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph with no wasted words. The main purpose and mode distinction are front-loaded, followed by precise constraints and defaults. Every sentence adds crucial information for correct invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a tool with nested objects, no output schema, and minimal annotations, the description is largely complete: it covers modes, time units, minimal required fields, ID omission, and undo behavior. It does not specify whether Path mode coexists with or replaces existing XY position, but otherwise provides sufficient context for correct use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaningful simplification beyond the schema: 'Keys need only t_us/value (Linear, identity tangents); nodes need only point (Line, Corner, zero handles)' and 'IDs are generated; omit all node/key ids.' These clarify usage of the deeply nested schema and reduce ambiguity about required fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Replace) and resource (a layer's position) and enumerates the two supported modes (XY tracks or a motion path with a progress track). This clearly distinguishes it from sibling tools like set_param_track or move_layer, and adds a key behavioral differentiator: 'Existing XY animation is replaced only by this explicit call.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for use: it replaces position outright, supports XY or Path modes, and notes that IDs are generated so they should be omitted. It also clarifies times are layer-local µs. However, it does not explicitly name alternatives (e.g., set_param_track, move_layer) or state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_preserve_pitchB
Idempotent

Set the pitch policy for explicitly selected Audio or Group clips. Defaults to true.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idsYesAudio or Group clips
preserve_pitchYesKeep pitch when changing duration.

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, so the safety profile is covered and the bar is lower. The description adds that the policy applies only to explicitly selected clips and mentions a default, but says nothing about authentication needs, reversibility of pitch changes, or interaction with retiming operations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action and scope. The trailing 'Defaults to true' is slightly ambiguous given preserve_pitch is a required parameter, but the overall structure is efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter, non-destructive, idempotent toggle with full schema coverage and no output schema, the description supplies enough context to call it correctly. The main residual gap is the missing relationship to retiming siblings and the ambiguous default clause.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters are fully described in the schema ('Audio or Group clips' and 'Keep pitch when changing duration'), so the description cannot add much. Its phrase 'explicitly selected Audio or Group clips' loosely reinforces the layer_ids scope but provides no new syntax or semantic detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Set') and resource ('pitch policy') scoped to 'explicitly selected Audio or Group clips,' so the operation is unambiguous. It does not, however, distinguish itself from adjacent sibling tools such as retime_layers or set_frame_interpolation that also touch audio/clip timing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Only a faint selection precondition ('explicitly selected') is implied; there is no statement of when to reach for this tool versus the many other audio/retime/pitch-related siblings, and no when-not or exclusion guidance. An agent must infer the trigger condition entirely.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_project_settingsA
Idempotent

Update the project's editing preferences; only the fields you send apply, and an unknown key or an empty patch is refused. Unrecorded — preferences are setup, patched into every history snapshot, so undo walks past them (the update_composition contract). Fields: auto_pair_audio_on_import, prefer_proxies, proxy_override, shot_review, pause_review (the last two validated and refused as a whole, against the detectors' own bounds; null clears one back to defaults), correction_script (what correct_caption_text corrects against). Returns { settings, changed }; changed names the fields that moved (empty: all already set). Read current values from project://settings.

ParametersJSON Schema
NameRequiredDescriptionDefault
patchYesSettings patch. Only the fields you include are applied; `null` has a per-field meaning given below and is never 'unset'.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses a high-value trait annotations do not cover: the change is 'Unrecorded' and preferences get patched into every history snapshot, so undo walks past them. It also explains refusal behavior (unknown keys, empty patch, out-of-bounds shot/pause values) and the per-field meaning of `null`. This goes well beyond idempotentHint/destructiveHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and its contract, then fields, then return shape. Dense with nested parentheses, but nearly every clause carries information an agent needs (refusals, undo behavior, cross-tool links) rather than restating the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-patch-object mutation tool with rich nested schema, the description covers write semantics, null handling, refusal cases, undo interaction, and the return shape (`{ settings, changed }`), plus where to read current state. Nothing essential to calling it correctly is missing despite there being no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning: it enumerates the patchable fields, clarifies that `null` clears to defaults rather than unsetting, and links `correction_script` to correct_caption_text and shot/pause settings to their detector tools. It stops short of describing every nested key's effect.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Update the project's editing preferences') and immediately scopes it ('only the fields you send apply'). This is clearly distinguishable from sibling mutations like update_composition, set_track_flags, or update_layer.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the patch contract (partial apply, unknown key refused, empty patch refused) and tells the agent where to read current values (`project://settings`). It also ties fields to the tools that consume them (analyze_clip, detect_pauses, correct_caption_text), effectively defining when the setting matters, though it never states an explicit when-not-to-use condition or alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_role_flagsA
Idempotent

Mute/solo an audio role. role ∈ {dialogue,music,sfx,voiceover}. Unrecorded (not undoable). Mute wins over solo; any solo silences non-soloed roles.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleYesThe mixing bus.
soloNoPlay this bus alone. Omitted leaves it alone.
mutedNoSilence the bus. Omitted leaves it alone.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare idempotentHint=true and destructiveHint=false, so the safety profile is already covered. The description adds valuable behavioral context beyond annotations: 'Unrecorded (not undoable)' warns that the operation cannot be undone, and 'Mute wins over solo; any solo silences non-soloed roles' explains the interaction semantics. This is exactly the kind of behavioral detail that helps an agent predict outcomes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero waste. The core action and allowed values are front-loaded, followed by the critical behavioral caveats. Every sentence earns its place, and the structure is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 3-parameter tool with full schema coverage and safety annotations, the description is nearly complete. It covers the action, the allowed values, the undo behavior, and the mute/solo interaction. The only minor gap is that it doesn't describe the return value or confirm what 'omitted leaves it alone' means for the resulting state, but with no output schema and a simple boolean toggle, this is a minor omission.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters. The description adds the enum values for role and the interaction rule between solo and muted, but it doesn't add meaning beyond what the schema provides for the parameters themselves. Baseline 3 is appropriate when the schema carries the full parameter documentation burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Mute/solo') and resource ('an audio role'), and enumerates the exact allowed values for the role parameter. It clearly distinguishes this from sibling tools like set_role_gain (which adjusts gain rather than mute/solo state) and set_track_flags (which operates on tracks, not roles).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool: when muting or soloing an audio role. It does not explicitly name alternatives or exclusions, but the sibling set includes set_role_gain, which is the natural alternative for gain adjustments, and the description's focus on mute/solo makes the boundary clear. No explicit when-not-to-use guidance is given, but the context is sufficient for an agent to select it correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_role_gainA
Idempotent

Set an audio role's mix gain (dB). role ∈ {dialogue,music,sfx,voiceover}. Recorded (undoable). Folds into every layer of that role at mix time.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleYesThe mixing bus.
gain_dbYesBus gain, dB; 0 = unity.

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses that the operation is recorded/undoable and that it folds into every layer of the role at mix time rather than editing individual clips. This adds meaningful behavioral context and does not contradict the idempotentHint or destructiveHint annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, with the core action and resource front-loaded. The role set, undoability, and mix-time behavior are all relevant, and there is no filler or redundant restating of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with idempotent and non-destructive annotations, the description covers the role domain, the gain unit, undoability, and the mix-time effect across layers. The only gap is explicit guidance on when to choose this tool over related siblings, but that is a usage-guidelines concern rather than a completeness failure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with both parameters already documented, including the role enum and dB semantics with 0 = unity. The description restates the role set and gain concept but adds little new parameter-specific meaning beyond that.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific operation ('Set an audio role's mix gain'), enumerates the allowed role values, and clearly identifies the resource. It distinguishes itself from related sibling tools like set_role_flags by focusing on audio role gain in dB.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context that the tool affects every layer of a role at mix time, implying it is the right choice for role-wide gain adjustment. However, it does not explicitly state when to use this tool versus alternatives or list any exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_scale_linkedA
Idempotent

Toggle a layer's uniform-scale link (visual kinds only). linked=true snaps scale_y to a whole-track copy of scale_x — keyframes included — in the same commit; linked=false clears only the flag. While linked, any write that leaves the two tracks unequal (a single-axis update_layer_params, set_keyframe, delete_keyframe, set_param_track) clears the flag in that commit — write both axes identically to keep it.

ParametersJSON Schema
NameRequiredDescriptionDefault
linkedYestrue links scale_y to scale_x; false clears the flag only.
layer_idYesLayer id.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare idempotentHint=true and destructiveHint=false. The description goes far beyond them by disclosing the same-commit copy behavior, the keyframe inclusion, the flag-clearing side effects of single-axis writes, and the requirement to write both axes identically. This is rich behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact but information-dense. The main action is front-loaded, and the conditional edge cases are clearly separated. Every sentence earns its place; no filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no output schema, this description covers the essential behavior completely: what the tool does, what the linked flag means in both states, how keyframes are handled, and how subsequent writes can affect the flag. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters already have meaningful descriptions. The description adds extra semantics for 'linked' by explaining exactly what true and false do in practice, including the auto-clearing behavior. This adds value beyond the schema, though layer_id needs no further elaboration.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Toggle'), a precise resource ('a layer's uniform-scale link'), and a scope restriction ('visual kinds only'). The first sentence alone distinguishes this from sibling tools like set_track_flags or update_layer_params.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit behavioral context: when linked=true, scale_y is snapped to scale_x including keyframes; when linked=false, only the flag is cleared. It also tells the agent exactly when the link will be auto-cleared and how to keep it intact, which is strong usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_track_flagsA
Idempotent

Set a track's enabled and/or locked flag; omit (or null) one to leave it alone, and name at least one. locked is what every TrackLocked refusal points at — a locked track rejects edits to its layers, and clearing it here is the fix. enabled is the track's output in preview and export; its layers stay put. A layer's own locked is separate (update_layer), and an edit needs both clear. Mute/solo live on roles: set_role_flags. Unrecorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
lockedNoWhether the track refuses edits to its layers. Omitted leaves it alone.
enabledNoThe track's output, preview and export alike. Omitted leaves it alone.
track_idYesTrack id.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint and destructiveHint, so the description only needs to add extra behavioral context. It does: it explains what `locked` means in terms of edit refusals, that `enabled` controls output while layers stay put, that layer-level `locked` is independent, and that the operation is unrecorded.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: the first sentence states the operation and the omit/null rule, subsequent sentences clarify flag semantics and sibling tools, and the trailing 'Unrecorded' is a terse but valuable disclosure. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter, simple boolean mutation with idempotent and non-destructive annotations, the description is nearly complete. The only small gap is that the schema does not technically enforce 'name at least one' flag, and the description doesn't state what happens if both are omitted, though its instruction makes that an unlikely agent error.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the parameters are already documented; the description adds useful meaning beyond the schema by explaining the 'at least one' rule, the distinct effects of `enabled` and `locked`, and how the track's `locked` flag relates to edit refusals.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Set a track's `enabled` and/or `locked` flag'. It immediately distinguishes this tool from siblings like `set_role_flags` and `update_layer` by stating that mute/solo live on roles and layer-level locking is handled elsewhere.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit usage guidance: omit/null one flag to leave it alone, name at least one flag, and clearing `locked` is the fix for `TrackLocked` refusals. It also names alternatives (`update_layer`, `set_role_flags`) and clarifies when they are relevant.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

shift_layersA

Shift a set of layers in time by one delta_us, as one recorded edit — the multi-layer move, and at from_t_us with a positive delta the ripple INSERT (open a gap, then place into it; a negative delta closes one). Name the set with layer_ids (link partners ride along unless escape_link) or with from_t_us (every layer starting at or after it, on track_ids or on every track). Each layer snaps on its own grid; its record's adjusted says where it landed. Nothing moves on a refusal: a sweep splitting a link (ShiftLinkStraddles — use layer_ids), a start crossing 0, an occupied landing, a locked lane. Returns { moved: [layer records], delta_us }.

ParametersJSON Schema
NameRequiredDescriptionDefault
delta_usYesSigned shift, µs; positive moves later. Not 0.
from_t_usNoShift every layer starting at or after this time, timeline, µs.
layer_idsNoThe layers to shift, all in one composition. Exactly one of this and `from_t_us`.
track_idsNoWith `from_t_us`: only these tracks. Omit for every track.
escape_linkNoWith `layer_ids`: leave link partners in place. Default false.
composition_idNoWith `from_t_us`: the composition to sweep; omit for the root.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide `destructiveHint: false`, so the description carries the full burden. It discloses the ripple insert behavior, grid snapping, refusal conditions (link straddle, crossing 0, occupied landing, locked lane), the `adjusted` field on records, and the return structure. This is comprehensive and consistent with the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-structured, front-loading the core action and then covering modes, snapping, refusals, and return. Every sentence adds value, though it is lengthy. It is appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 parameters, two modes, multiple refusal conditions) and the absence of an output schema, the description explains the return value and behavior thoroughly. It does not cover every conceivable edge case, but it provides enough for an agent to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema, such as the mutual exclusivity of `layer_ids` and `from_t_us`, the behavior of `escape_link`, and the scope of `track_ids`. It does not contradict the schema and clarifies the interactions between parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'shift' and the resource 'layers in time', and explains the multi-layer move and ripple insert. It is specific but does not explicitly name sibling tools to differentiate, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly distinguishes between the `layer_ids` and `from_t_us` modes, explains when each is appropriate, and even recommends using `layer_ids` when a sweep would split a link (`ShiftLinkStraddles`). This is explicit guidance on when to use the tool and how to handle a refusal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

smooth_keyframesA
Idempotent

Set Auto tangents (clamped monotone, solved on write and kept smooth as neighbours move) on one key, or every key when keyframe_id is omitted. Both sides of each key go Auto with Smooth continuity, and the adjacent segments become Spline. get_param_track reads the solved coordinates back with mode "Auto".

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].
keyframe_idNoOne key to smooth; omit for every key of the track.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only idempotentHint and destructiveHint in annotations, the description adds substantial behavioral context: both sides of each key go Auto with Smooth continuity and adjacent segments become Spline, plus the tangent is 'solved on write and kept smooth as neighbours move.' It stops short of stating overwrite semantics or required permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the primary action and its mechanics, with no filler. Slightly dense but every clause conveys distinct behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, it explains what changes (tangents, adjacent segments) and points to get_param_track for reading results. Complete enough to invoke correctly, missing only edge-case behavior on non-keyed tracks.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all three parameters. The description's keyframe_id scoping note ('or every key when keyframe_id is omitted') largely restates the schema description, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Set Auto tangents') and resource (keyframe tangents), and specifies the exact mode (clamped monotone, solved on write). It distinguishes itself from siblings like set_keyframe/update_keyframe by describing the tangent/continuity behavior rather than generic key editing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly explains scope selection: one key when keyframe_id is given, every key when omitted, and references get_param_track for reading solved coordinates. However, it does not explicitly compare against the close siblings set_keyframe/update_keyframe or state when this should be preferred over them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

split_layerA

Split at sorted, grid-snapped times in one atomic edit. Each half retains its mapped content window. Linked members form a separate link per segment unless escape_link. Returns layer_ids and actual at_t_us.

ParametersJSON Schema
NameRequiredDescriptionDefault
at_t_usYesInterior timeline cuts, µs; snapped, sorted, deduplicated. Any invalid cut rejects all.
layer_idYesLayer id.
escape_linkNoAct on this layer alone, leaving its link partners in place. Default false.

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the lone destructiveHint=false annotation, the description discloses meaningful traits: atomicity, that each half keeps its mapped content window, link-splitting behavior unless escape_link, and the return payload (layer_ids, actual at_t_us). This is consistent with the non-destructive hint rather than contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action and outcome. Dense but every clause carries behavioral information; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and only a destructiveHint annotation, the description covers atomicity, content preservation, link handling, and return shape well. Only the usage/routing guidance is missing, which is scored separately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds value: 'sorted, grid-snapped' qualifying at_t_us, the escape_link exception, and the fact that returned at_t_us may differ from requested due to snapping. That goes beyond the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('split at ... times') and adds scope ('one atomic edit', 'grid-snapped'), which is enough to separate it from sibling auto_split_by_shot. However it never explicitly names or contrasts that sibling, so differentiation is implicit rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use, when-not-to-use, or alternative routing is given. The description explains how the split behaves but not the conditions under which an agent should pick split_layer over auto_split_by_shot, trim_layer, or ripple_delete_gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

synthesize_speechA

Synthesize speech with the configured cloud TTS provider (OpenAI tts-1) and place it as an Audio layer. text ≤ 4096 chars; voice is one of alloy / echo / fable / onyx / nova / shimmer; optional speed 0.25..4.0 (default ≈ 1.0); optional target_track_id (default: the first Audio track, else a new 'Voiceover' track); optional t_start_us (default: the composition's current duration, so the clip appends at the end). The MP3 is cached by (model, voice, speed, text), so a repeat call costs no API request. Returns { layer_id, media_id, t_start_us, t_end_us, cached }.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesText to synthesize. tts-1 caps at 4096 characters.
speedNo0.25..4.0 for tts-1. Omit to use the provider default (~1.0).
voiceYesVoice identifier. tts-1 accepts: alloy, echo, fable, onyx, nova, shimmer.
t_start_usNoOptional timeline start in microseconds. Defaults to the composition's current `duration_us` so the voiceover appends at the end.
target_track_idNoOptional Audio track id. If omitted, lands on the first existing Audio track or auto-creates one labeled "Voiceover".

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (destructiveHint: false), the description discloses key behaviors: caching by (model, voice, speed, text) so repeat calls cost no API request, default track selection logic, and the return object shape. It also clarifies that t_start defaults to the composition's current duration, which is non-obvious. This goes beyond typical descriptions and does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense yet concise. It front-loads the purpose, then delivers constraints, defaults, caching, and return format in a logical order. Every sentence carries operational value, with no fluff or repetition. It is well-structured for an agent to quickly extract actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 5 parameters and no output schema, the description is remarkably complete. It covers all parameter semantics, defaults, caching behavior, and the return object. There is no ambiguity about how to invoke it or what to expect. It also addresses edge cases like track creation and caching, leaving no critical gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds value by explaining the caching key, the default behavior for t_start_us (append at end), and the track selection fallback. It also enumerates voice options and speed range, reinforcing the schema without redundancy.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: synthesize speech with the configured cloud TTS provider and place it as an Audio layer. It names the specific provider (OpenAI tts-1), making the resource explicit. Among siblings, none directly synthesize speech, so it is uniquely identifiable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: it specifies input constraints (text ≤ 4096 chars, voice options, speed range), default behaviors (target track, t_start), and caching semantics. However, it does not explicitly name alternative tools or state when not to use it, but given its uniqueness, the guidance is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

transcribe_clipA
Read-only

Transcribe a VideoClip or Audio layer with the configured engine (cloud OpenAI Whisper, or local whisper.cpp / FunASR). Returns { backend, segments: [{ t_start_us, t_end_us, text, words: [{ t_start_us, t_end_us, text }] }], language, word_timing } in timeline-absolute µs. Hand the envelope to apply_transcripts to lay captions that keep the word timing. word_timing is "exact" or "interpolated_from_cue". Optional t_start_us/t_end_us narrow the window; backend ("openai" | "whisper_cpp" | "funasr") REQUIRES that engine — it errors naming the missing key / binary / model rather than substituting, so a local choice never uploads; omitted, the user's preferred engine then availability. word_timestamps (default true) asks for exact per-word times where the engine can (OpenAI is SRT-only). Retimed segment and word times are projected onto the timeline. Errors name the cause: no engine, the provider cap (~13 min for cloud Whisper), rate limits, auth.

ParametersJSON Schema
NameRequiredDescriptionDefault
backendNoStrict engine override: `"openai"` | `"whisper_cpp"` | `"funasr"`. That engine serves or the call errors; nothing is substituted. Omitted: the user's preferred engine, then availability.
languageNoOptional ISO-639-1 language hint (`"en"`, `"zh"`). Auto-detect when omitted.
layer_idYesTarget VideoClip or Audio layer id.
t_end_usNoOptional transcription window end in timeline microseconds. Defaults to the layer's `t_end_us`. Must lie within the layer.
t_start_usNoOptional transcription window start in timeline microseconds. Defaults to the layer's `t_start_us`. Must lie within the layer.
word_timestampsNoAsk for exact per-word times where the engine can emit them. Default true; `false` forces SRT-style interpolated words. The result's `word_timing` reports what you got.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Given readOnlyHint=true, the description goes well beyond annotations: it discloses error behavior, the ~13 min cloud provider cap, rate limits, auth failures, that a local backend never uploads, and the meaning of word_timing values. This is exactly the extra context the annotation bar leaves room for.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose and return shape, then parameters, then errors. Dense but every clause earns place; slightly long for the amount of near-duplicate backend wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the return-value burden and does so fully with the envelope shape and word_timing semantics. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds non-schema detail such as OpenAI being SRT-only for word timestamps and the retiming/projection of segment and word times onto the timeline. Some engine-strictness detail overlaps the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (transcribe a VideoClip/Audio layer), names the engine choices, and describes the returned envelope shape. An agent can distinguish it from siblings like extract_clip_audio or analyze_audio without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to the follow-up tool (hand the envelope to apply_transcripts) and explains engine-selection policy when backend is omitted. Lacks an explicit 'when not to use this / use X instead' clause, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

translate_pathA

Translate the entire spatial path in composition pixels, preserving its geometry and progress animation. Requires Path mode. One undo step.

ParametersJSON Schema
NameRequiredDescriptionDefault
dxYesShift in x, composition px.
dyYesShift in y, composition px.
layer_idYesLayer id.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the single destructiveHint=false annotation, the description discloses useful behavioral traits: it preserves geometry and progress animation and is reversible in one undo step. It also states a mode requirement. This is meaningful context without overclaiming; it doesn't describe error behavior, but that is a minor gap for such a simple operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences deliver the action, scope, semantic guarantee, precondition, and undo behavior with no filler. The main operation is front-loaded and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple transform with three fully described parameters, no nested objects, and no output schema, the description covers the essential context: what is translated, the coordinate units, the mode prerequisite, the preservation behavior, and undo granularity. An agent has enough to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already defines dx, dy, and layer_id clearly, including composition-pixel units. The description's mention of composition pixels reinforces the schema but doesn't add per-parameter meaning beyond it. A baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action ('Translate') on a specific resource ('the entire spatial path') with clear units ('composition pixels') and semantic guarantees ('preserving geometry and progress animation'). The mention of 'Path mode' further distinguishes it from sibling layer-movement tools like move_layer or shift_layers.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a necessary precondition ('Requires Path mode') but no explicit guidance about when to prefer this over alternatives such as move_layer, shift_layers, or set_position. It implies the use case by naming the path resource, but does not state exclusions or alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

trim_layerA
Idempotent

Trim an edge to new_t_us. Source time follows the clip rate; keyframes remain glued to content. Aligned linked edges follow unless escape_link. Refuses targets outside the legal source/timeline window. Returns committed spans, trimmed siblings and grid adjustments.

ParametersJSON Schema
NameRequiredDescriptionDefault
edgeYesWhich edge moves: in = t_start_us, out = t_end_us.
layer_idYesLayer id.
new_t_usYesWhere the edge lands, timeline, µs.
escape_linkNoAct on this layer alone, leaving its link partners in place. Default false.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotent=true and non-destructive, and the description adds meaningful behavior on top: source time follows the clip rate, keyframes stay glued to content, aligned linked edges follow unless escape_link, and out-of-window targets are refused. This is rich context beyond the annotations, though it omits auth/side-effect details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense and front-loaded — the core action leads, followed by behavioral qualifiers and the return shape. Each clause carries information, though the run-on opening sentence packs several distinct facts without separation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully enumerates the return (committed spans, trimmed siblings, grid adjustments) and covers validation and link propagation. A mutation tool without annotations on permissions would benefit from more, but this is nearly complete for the call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so baseline is 3, but the description adds real semantics: new_t_us interacts with clip rate and keyframes, and escape_link controls whether link partners move. That goes beyond the schema's terse field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Trim) and resource (edge) with the target parameter named, so the operation is unambiguous vs siblings like split_layer or move_layer. It doesn't explicitly distinguish itself by name from close siblings such as retime_layers or set_scale_linked, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implied usage is derivable (trim when you want to move an in/out point), and the linked-edge propagation is described, but there is no explicit when-to-use / when-not-to-use guidance or named alternative among the many sibling tools. Adequate but generic.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

undoA
Destructive

Undo the most recent edit (linear history); NothingToUndo at the origin. Only timeline edits record — layers, tracks, markers, transitions, links, and media removals that cascade. Outside the stack and untouched by undo: media imports, the composition envelope (update_composition), project settings (set_project_settings), track and role flags, and loading a project (which resets history). Answers undone: the op reverted.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply `destructiveHint: true`; the description adds substantial behavioral detail the annotations cannot: the linear (non-branching) history model, the origin error condition, exactly which edit classes are recorded, which are excluded, and that loading a project resets history. It also discloses the `undone` return field despite no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and error case, then the recording rules, then the exclusions. It is dense and semicolon-chained, which hurts scanability slightly, but nearly every clause carries real information and nothing is redundant with structured fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter mutation with only `destructiveHint` and no output schema, this covers everything an agent needs: scope of effect, failure mode, exclusion list, history-reset behavior, and the return signal. No remaining gap is material.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline is 4. The description correctly adds no parameter syntax, but it does clarify the implicit output semantics ('Answers `undone`: the op reverted'), which is the only argument-like contract this tool has.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Undo the most recent edit') and pins the scope explicitly as linear history with an origin sentinel (`NothingToUndo`). An agent can distinguish this from the sibling `redo` without further inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides unusually strong when-not guidance by enumerating what does not enter the undo stack (media imports, `update_composition`, `set_project_settings`, track/role flags, project loading). It stops short of naming the natural alternative `redo` for forward traversal, so it is clear context without full routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ungroup_layerA

Expand a Group layer back into its members, in place. Refuses unless the Group is PLAIN — identity transform, static opacity 1, no effects, Normal blend (GroupNotPlain { reason }), because those apply to the composite and would be discarded; reset them first or keep the Group. Members intersecting the Group's [src_in_us, src_out_us) window are copied into the parent at the same on-screen time, trimmed to the window; members wholly outside are dropped. The composition's tracks become fresh tracks at the Group's z position; inner links and transitions carry over. The composition is removed when nothing else references it. One undo restores the Group.

ParametersJSON Schema
NameRequiredDescriptionDefault
layer_idYesThe Group layer (its params.kind is CompositionRef).

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses detailed behavioral traits beyond the destructiveHint=false annotation: the PLAIN requirement, the trimming of members to the [src_in_us, src_out_us) window, dropping of wholly outside members, creation of fresh tracks at the Group's z position, carry-over of links/transitions, conditional removal of the composition, and the undo behavior. No contradiction with annotations; the removal is conditional and undoable, so destructiveHint=false is consistent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-structured, front-loading the main action and then logically covering the refusal condition, member handling, track/link behavior, removal, and undo. Each sentence contributes necessary detail for a complex operation; it is not bloated, though it could be slightly tightened without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex ungroup operation with many edge cases, the description covers all essential aspects: the precondition, member trimming/dropping, track re-creation, link/transition carry-over, composition removal condition, and undo restoration. There is no output schema, but the description sufficiently explains what happens, so nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage for layer_id, explaining it as 'The Group layer (its params.kind is CompositionRef).' The description adds no further parameter-specific semantics beyond what the schema already provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Expand a Group layer back into its members, in place,' which names a specific verb, resource, and result. It clearly distinguishes this from sibling operations like create_group or add_group_members by describing the inverse behavior. The refusal condition and member-handling details further reinforce the specific purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states a clear precondition: the Group must be PLAIN, and advises 'reset them first or keep the Group' if not. This gives the agent explicit guidance on when the tool is applicable and what to do if the precondition fails. It does not name alternative tools, but no direct alternative exists—this is the dedicated ungroup operation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_compositionA
Idempotent

Update a composition's envelope — canvas width/height, fps, sample_rate, channels, color_space, background, duration_us; only fields you set apply; composition_id names a Group's composition, the root when omitted. Unrecorded: the envelope is setup, so the patch reaches every history snapshot and undo walks past it. fps is LOCKED once the timeline, any history snapshot or any checkpoint holds a layer — refused with FpsLockedByContent { current, requested, layer_count, locked_by: "current" | "history" }; set the rate on a project that has never held a layer, or empty the timeline and reopen the project to clear a history lock. sample_rate is never locked. Setting duration_us PINS the duration so layer edits stop auto-fitting it; duration_us: null (alone in the patch) unpins it and refits to the layers.

ParametersJSON Schema
NameRequiredDescriptionDefault
patchYesComposition envelope patch. Only fields you set are applied.
composition_idNoThe composition to patch; omit for the root. fps / sample_rate / channels are one lattice for the whole project and cascade to every composition.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses behavioral traits that the idempotentHint/destructiveHint annotations never cover: 'the envelope is setup, so the patch reaches every history snapshot and undo walks past it' — a critical non-obvious side effect. It also gives the full failure surface, including the error shape (FpsLockedByContent { current, requested, layer_count, locked_by }) and the contrast that 'sample_rate is never locked.' No contradiction exists with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded, opening with the verb, resource, and field list before arriving at nuance. Each sentence earns its place — the unrecorded-history clause, the lock conditions with error type, and the pin/unpin semantics all carry information absent elsewhere — though the length is near the practical limit for quick parsing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (nested patch object, conditional locking, history interaction with undo), the description covers every decision-relevant case: omission semantics for composition_id, the non-obvious undo behavior, the locked-by history variant, and the duration unpin path via null. The schema already documents parameter formats at 100%, so the only modest gap is unspecified success/return behavior — minor for a mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: it elaborates the lock precondition ('once the timeline, any history snapshot or any checkpoint holds a layer'), spells out the error variant semantics, and explains the auto-fit interaction between duration_us pinning and layer edits. It genuinely enriches the schema rather than repeating it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource — 'Update a composition's envelope' — and enumerates the exact patchable fields (canvas width/height, fps, sample_rate, channels, color_space, background, duration_us), which cleanly separates it from siblings like update_layer, rename_composition, and set_project_settings. It further pins scope by clarifying that composition_id names a Group's composition, root when omitted.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives concrete operational conditions: fps is settable only when no layer exists anywhere, with the exact refusal path (FpsLockedByContent) and an explicit escape hatch ('empty the timeline and reopen the project to clear a history lock'), plus the duration_us pin/unpin usage rule. It does not name an alternative sibling for explicit when-not routing, so the boundary with update_layer/update_layer_params is inferred rather than pointed at.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_effectA
Idempotent

Update an effect: patch is { enabled?, params? } where params is { paramKey: { "mode": "Static", "value": <number> } } (v1 params are scalar). A null param value removes the key (back to unset/default). For keyframed params use set_keyframe with param_key "effects[].params[]". An unparseable patch (non-object, unknown key, malformed param value) rejects with invalid_params — it never partially applies.

ParametersJSON Schema
NameRequiredDescriptionDefault
patchYesEffect patch. Only fields you set are applied; `params` merges key-by-key, and a null value removes its key.
layer_idYesLayer id.
effect_idYesEffect id.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

It discloses key behavioral traits beyond annotations: null removes a param key, unparseable patches are rejected with invalid_params, and the patch never partially applies. Since idempotentHint and destructiveHint are already in annotations, the description adds meaningful atomicity and validation context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but efficient: it opens with the core action, immediately gives the patch shape, covers the null-removal edge case, routes keyframed work to a sibling, and closes with error semantics. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the 100% schema coverage, full annotations, and no output schema, the description covers everything needed to invoke the tool correctly: patch syntax, merge behavior, alternative tool for keyframing, and failure atomicity. No critical usage gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds compact guidance on the exact patch structure and the null-removal semantics. It also flags the error behavior for malformed patches, which goes beyond the schema's field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Update' and the resource 'effect' with an exact patch shape, so an agent knows what the tool does. It also distinguishes itself from set_keyframe by explicitly routing keyframed params to that sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description says exactly when to use this tool — for scalar/static effect param updates — and when not to: for keyframed params, use set_keyframe with the proper param_key. This is an explicit alternative with a concrete condition, leaving no ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_keyframeA
Idempotent

Change one keyframe in one commit — any of: t_us (move it, timeline-absolute; the track re-sorts), easing (the segment LEAVING the key: {"preset":""} from the canonical table, read back as preset_id, or a raw kind {"kind":"Hold"} | {"kind":"Linear"} | {"kind":"Bezier","p1":[x,y],"p2":[x,y]} | {"kind":"Elastic","dir",amplitude?,period?} | {"kind":"Bounce","dir"}; writes this key's out tangent and the next key's in tangent, both Free), in / out (one side's tangent {x, y}, stored Free — x within [0, 1], y may overshoot — its segment becoming Spline; a side written on an Auto key frees the whole key), continuity ("Smooth" re-derives in from out, "Broken" changes no number). At least one; applied in that order. Auto tangents on one or every key: smooth_keyframes.

ParametersJSON Schema
NameRequiredDescriptionDefault
inNoA tangent to write: {x, y} in the owning segment's unit square — x within [0, 1] (refused outside), y may overshoot. Stored Free.
outNoA tangent to write: {x, y} in the owning segment's unit square — x within [0, 1] (refused outside), y may overshoot. Stored Free.
t_usNoNew timeline-absolute time, µs.
easingNoEither {"preset":"<id>"} — a canonical named preset, baked to its params — or a raw kind (same forms as set_keyframe interp).
layer_idYesLayer id.
param_keyYesVisual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>].
continuityNoSmooth keeps the two sides at one slope (re-derived from `out`); Broken lets them differ.
keyframe_idYesKeyframe id.

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover idempotency and non-destructiveness, so the description carries the behavioral burden and does so richly: `t_us` re-sorts the track, an `easing` write also rewrites the NEXT key's in tangent, writing a side on an Auto key frees the whole key, and `Smooth` re-derives `in` from `out` while `Broken` changes no number. These cross-key side effects and the write ordering are exactly the kind of behavior an agent cannot infer from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, which is good, but it compresses everything into one dense run-on clause whose nesting is hard to parse. It also re-enumerates the easing kind forms ({kind:'Hold'}|{kind:'Linear'}|...) that the schema enum already supplies, so not every token earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 8-parameter mutation tool with no output schema, the description covers param interactions, ordering, and cross-key effects well, and annotations cover safety. It omits any return-value expectation or permission/auth context, but those gaps are minor for this operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage the baseline is 3, but the description adds real semantics beyond the schema: the segment-leaving meaning of `easing`, `x` refused outside [0,1] while `y` may overshoot, and the fixed application order of the fields. It goes past the structured fields rather than restating them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Change one keyframe in one commit') and enumerates exactly which fields can change, so the agent knows the tool's scope immediately. It distinguishes itself from the auto-tangent sibling by routing that case to `smooth_keyframes`, though it does not contrast with `set_keyframe` or `delete_keyframe`.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit usage constraint ('At least one; applied in that order') and points to `smooth_keyframes` for the auto-tangent case, which is a genuine alternative routing. However, it never states the general when-to-use versus `set_keyframe`, so it stops short of full when/when-not/alternatives coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_layerA
Idempotent

Update a layer's envelope: label, t_start_us/t_end_us, locked. Only fields you set apply; time changes are validated; any other key is refused naming the set. Visibility is set_layers_enabled; kind-specific params are update_layer_params. Locks reject content edits; unlock with a separate lock-only patch.

ParametersJSON Schema
NameRequiredDescriptionDefault
patchYesEnvelope patch; only the fields you set apply.
layer_idYesLayer id.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry idempotentHint and destructiveHint=false; the description adds substantially more: partial-patch semantics (only set fields apply), time-change validation, rejection of unknown keys, and the fact that locks block content edits but must be lifted via a separate patch. That is exactly the behavioral depth the annotations do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the verb and the affected fields, then progressively adds constraints, error behavior, and sibling routing in short clauses. No sentence is filler; each one either scopes the operation or prevents a misuse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers partial-update semantics, validation, error behavior, lock interaction, and the correct sibling for adjacent concerns. Nothing needed to invoke it correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the per-field descriptions already carry the baseline burden. The description still adds meaning beyond the schema by stating that only explicitly-set fields apply, that time changes are validated (schema only mentions snapping/echoing), and that unrecognized keys are refused by name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (update) and a precisely scoped resource (a layer's envelope), then enumerates the exact fields in scope: `label`, `t_start_us`/`t_end_us`, `locked`. It also draws the boundary against two named siblings (`set_layers_enabled`, `update_layer_params`), so an agent can route correctly without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing rules: visibility changes go to `set_layers_enabled`, kind-specific parameters go to `update_layer_params`, and unlocking requires a separate lock-only patch. It also states the failure condition (any other key is refused), which is effectively a when-not rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_layer_paramsA
Idempotent

Patch static fields of one clip. Path mode rejects independent x/y writes. Text has no scale fields; resize its box. Animated fields become Static; use set_param_track for animation. Source edits trim content; retime_layers changes playback rate. Fields are kind-specific (schema variants). Returns the updated clip; locked clips and invalid values are refused.

ParametersJSON Schema
NameRequiredDescriptionDefault
patchYesKind-tagged patch: `kind` must match the layer's, and only that kind's fields are accepted (one variant per kind); a key outside the set is refused naming it.
layer_idYesLayer id.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply idempotentHint and destructiveHint=false, so the description carries most of the behavioral burden and does it well: animated fields are flattened to Static, source edits trim content, locked clips and invalid values are refused, and it returns the updated clip. It stops short of stating permission/auth requirements or what 'refused' looks like on the wire, but the mutation semantics are unusually well disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Six tight sentences with zero padding, each carrying a distinct constraint, and the core action plus the highest-risk restriction (Path mode) are front-loaded. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex kind-variant mutation tool with no output schema, the description covers refusals, side effects on animated/source fields, alternative tools, and the return value. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters and every kind variant, establishing a baseline of 3. The description adds non-obvious cross-field meaning the schema alone does not surface, notably that fields are kind-specific and that Text has no scale fields so its box must be resized instead.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Patch static fields of one clip') and immediately scopes it against siblings by naming the exact cases it does not cover. An agent can distinguish it from update_layer, set_param_track, retime_layers, and set_position without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent elsewhere: 'use set_param_track for animation', 'retime_layers changes playback rate', and Path mode writes belong to set_position/translate_path. This is genuine when-to-use/when-not-to-use guidance, not implied usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_markerA
Idempotent

Update a marker. Setting t_us re-sorts the marker list. On a marker ANCHORED to a clip, t_us names the time the mark should read and moves the ANCHOR to make it read that, so the mark keeps following its clip from the new offset — a time outside that clip's span is refused, and t_us together with end_t_us is refused (an anchored region's end follows its anchor by itself; patch one or the other).

ParametersJSON Schema
NameRequiredDescriptionDefault
patchYesMarker patch; only fields you set apply. `end_t_us` can be set, never cleared (remove + re-add). The anchor is `set_marker_anchor`'s, not patchable here.
marker_idYesMarker id.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses substantial behavior beyond the annotations: setting t_us re-sorts the marker list, anchored markers move their anchor to honor t_us, out-of-span times are refused, and t_us cannot be combined with end_t_us on an anchored region. It also explains the reason ('an anchored region's end follows its anchor by itself'), which helps the agent avoid invalid calls. This is exemplary behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and then provides dense, necessary details about marker anchoring and constraints. While the anchored behavior explanation is long, every clause earns its place and is logically structured. It is not bloated, though it could be slightly tighter without losing substance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter patch-based update tool, the description covers the tricky behavioral cases (re-sorting, anchored movement, refused combinations) thoroughly. The patch object's own descriptions cover the remaining field semantics, and the output is presumably a simple success result. Minor gaps such as explicit return behavior and a direct 'when not to use' are absent, but the core calling context is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is already strong, but the description adds real semantic value: it explains the re-sorting side effect of t_us, the anchored-anchor-movement behavior, and the refusal rules for t_us and end_t_us combinations. These meanings are not present in the schema field descriptions and materially change how the parameters should be used.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with the crisp, specific verb+resource statement 'Update a marker,' which matches the tool name without being a pure tautology. It then elaborates on real behavior, making clear this tool modifies an existing marker rather than creating, deleting, or anchoring one. This distinguishes it effectively from siblings like add_marker, delete_marker, and set_marker_anchor.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit 'use this when...' or 'instead of...' guidance, and no exclusions against sibling tools. The intended context is implied: to modify an existing marker's fields or timing. The anchored-marker caveats give partial situational guidance, but the description never tells the agent how to choose between this and add_marker/delete_marker/set_marker_anchor.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_transitionA
Idempotent

Patch a transition's duration_us, kind/direction and/or extended_us in one recorded commit; only fields you set apply. direction rides with kind: switching to Wipe/Slide needs both, and direction alone or beside Crossfade is rejected. Geometry is two targets: extended_us is the borrowed share of the overlap (0 = pure placement, duration_us = pure borrow); the outgoing layer ends at its exit frame + extended_us, the incoming starts duration_us before that. With extended_us OMITTED the trimmed ranges are preserved — growing moves the incoming layer further left and never borrows, shrinking returns borrowed tail first then moves it right. Only an explicit extended_us grows the borrow (checked against the remaining tail: TransitionInsufficientHandle { available_us }); a NEGATIVE one is a deliberate tail trim of real content. Link siblings follow the incoming layer; a move onto occupied space or across t = 0 refuses the commit. TransitionNotFound for an unknown id.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoNew kind; send `direction` with Wipe / Slide.
directionNoMotion direction; rides with `kind` (Wipe / Slide need it, Crossfade refuses it).
duration_usNoNew transition length, µs.
extended_usNoBorrowed-tail target in µs, at most duration_us. Omit to preserve trimmed ranges; negative = deliberate tail trim of real content.
transition_idYesTransition id.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only convey idempotency and non-destructiveness. The description adds substantial behavioral detail beyond that: rejection of `direction` with Crossfade, geometric semantics of `extended_us`, tail-trim behavior for negative values, link-sibling side effects, commit refusals, and specific error variants such as `TransitionInsufficientHandle` and `TransitionNotFound`.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but dense, and every sentence carries unique information needed to call the tool correctly. It is front-loaded with the core patch semantics, then progressively explains parameter interactions, side effects, and error conditions without filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is highly complete for invocation: constraints, parameter semantics, side effects, and failure modes are covered in detail. The only mild gap is that it does not describe the success response or return shape, and there is no output schema to compensate, so an agent cannot know what a successful call returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description significantly deepens parameter understanding. It explains that `extended_us` is the borrowed share of overlap, how omitted versus explicit values change behavior, that negative values trim real content, and how `direction` must ride with `kind`. This goes well beyond the schema property descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Patch a transition's `duration_us`, `kind`/`direction` and/or `extended_us` in one recorded commit'. It enumerates exactly which fields are affected and clearly implies this is for updating an existing transition, distinguishing it from sibling add_transition and delete_transition.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operational context: partial updates only apply set fields, `direction` is coupled with `kind`, and omitting `extended_us` preserves trimmed ranges. However, it does not explicitly contrast with add_transition/delete_transition or state when the alternatives should be used, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

weftcut_statusA

Report whether the WeftCut desktop app is currently running and reachable, and which project it has open. Returns the endpoint state and what to do next when it is not running. Costs nothing; call this first when WeftCut tools appear to be missing or failing.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does reasonably well: it discloses the return content (endpoint state and next-step guidance), that it has no cost/side effects, and that it is a prerequisite diagnostic check. It does not explicitly state whether it is purely read-only or whether it can alter session state, which is the one remaining gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences, front-loaded with the core capability and followed by the failure-recovery guidance. Every sentence earns its place with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, no-output-schema diagnostic tool, the description supplies everything needed: what it checks, what it returns conceptually, and the actionable next step when the target is unreachable. No structural field is left unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4; there is nothing for the description to disambiguate. It correctly adds no parameter noise, which is appropriate for a parameterless status probe.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: reports whether the WeftCut desktop app is running and reachable, plus which project is open. This is clearly distinct from siblings like ping, launch_weftcut, or open_project, so an agent can tell them apart without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('call this first when WeftCut tools appear to be missing or failing') and notes it costs nothing, which strongly implies when to prefer it. It stops short of naming an alternative sibling (e.g., ping vs. this diagnostic) or stating when not to use it, so it is strong but not fully explicit routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_motif_draftA
Idempotent

Write a Motif draft from { manifest, html }. Returns { draft_id }. The draft is placeable immediately (via add_motif_layer) for preview, and re-writable. from (optional) records an existing Motif id as the draft's UPDATE target so a later install_motif {mode:'update'} republishes over it; omit from for a brand-new Motif (installs as new). The manifest's id/version are ignored — app-assigned. Companion files are copied from from when present. Expose tweakable controls via props_schema.

ParametersJSON Schema
NameRequiredDescriptionDefault
fromNoOptional id of an existing Motif this draft will UPDATE on install (records it as the draft's target). Omit for a brand-new Motif (installs as new).
htmlYesThe HTML body. The manifest island is injected by the app; a `<script>motif.define({...})</script>` drives the render.
manifestYesThe manifest object (`id`/`version` are app-assigned and ignored): `{ name, size: [w, h], default_duration_s, props_schema, ... }` — copy a built-in's from `get_motif_source`.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, so safety is covered, but the description adds genuine behavior: drafts are re-writable, manifest id/version are ignored and app-assigned, companion files are copied from `from`, and the draft records an update target for a later install. Those are real lifecycle facts not derivable from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and return value, then layers lifecycle context in a compact block. There is some redundancy — `from`'s omit-for-new behavior and the ignored id/version are each stated twice across description and schema — but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-param write tool with no output schema, the description supplies the return shape, the lifecycle relationship to add_motif_layer/install_motif, and the app-assigned manifest fields. Nothing an agent needs to author and use a draft correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters in detail; the description largely restates `from` and the manifest id/version behavior. It adds props_schema guidance for tweakable controls, but the marginal value over structured fields is modest, matching the baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Write) and resource (Motif draft) and specifies the exact inputs { manifest, html } and return shape { draft_id }. It also distinguishes itself from siblings by naming add_motif_layer for placement and install_motif for republishing, so an agent can place it precisely in the motif workflow.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the key branching decision: pass `from` to target an existing Motif for update-on-install, omit it for a brand-new Motif. It also notes the draft is immediately placeable for preview and re-writable. It stops short of explicitly contrasting when to prefer this over preview_motif_draft or install_motif directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.3.0
    • Addedget_frame_interpolation_capabilities
    • Addedretime_layers
    • Addedset_frame_interpolation
    • Changedset_param_track1 field changed
      • addedInput schema / properties / track / properties / value / items / properties / time_fraction
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Optional exact sub-microsecond remainder; keeps retimed keys unsnapped.",
        +  "properties": {
        +    "den": {
        +      "description": "Positive denominator; reduced fraction.",
        +      "type": "integer"
        +    },
        +    "num": {
        +      "description": "0 <= num < den.",
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "num",
        +    "den"
        +  ],
        +  "type": "object"
        +}
    • Addedset_preserve_pitch
    • Changedupdate_layer_params1 field changed
      • changedInput schema / properties / patch / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "align": {
        -        "description": "Horizontal alignment inside the box.",
        -        "enum": [
        -          "Left",
        -          "Center",
        -          "Right"
        -        ],
        -        "type": "string"
        -      },
        -      "anchor_x": {
        -        "description": "Pivot x, fraction of the width (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "anchor_y": {
        -        "description": "Pivot y, fraction of the height (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "box_h": {
        -        "description": "Layout box height, composition px, local (before `scale`). null = auto height. Refused when the layer has no box_w and the patch supplies none.",
        -        "exclusiveMinimum": 0,
        -        "type": [
        -          "number",
        -          "null"
        -        ]
        -      },
        -      "box_w": {
        -        "description": "Layout box width, composition px, local (before `scale`). null = auto width.",
        -        "exclusiveMinimum": 0,
        -        "type": [
        -          "number",
        -          "null"
        -        ]
        -      },
        -      "color": {
        -        "description": "Fill colour.",
        -        "properties": {
        -          "a": {
        -            "description": "Alpha 0..255; 255 opaque.",
        -            "type": "integer"
        -          },
        -          "b": {
        -            "description": "Blue 0..255.",
        -            "type": "integer"
        -          },
        -          "g": {
        -            "description": "Green 0..255.",
        -            "type": "integer"
        -          },
        -          "r": {
        -            "description": "Red 0..255.",
        -            "type": "integer"
        -          }
        -        },
        -        "required": [
        -          "r",
        -          "g",
        -          "b",
        -          "a"
        -        ],
        -        "type": "object"
        -      },
        -      "content": {
        -        "description": "The text; newlines are honoured.",
        -        "type": "string"
        -      },
        -      "font_family": {
        -        "description": "Font family name.",
        -        "type": "string"
        -      },
        -      "font_size_px": {
        -        "description": "Font size, composition px.",
        -        "type": "number"
        -      },
        -      "font_weight": {
        -        "description": "CSS weight 100..900; 400 regular, 700 bold.",
        -        "type": "integer"
        -      },
        -      "italic": {
        -        "description": "Italic face.",
        -        "type": "boolean"
        -      },
        -      "kind": {
        -        "const": "Text",
        -        "description": "Fields of a Text layer."
        -      },
        -      "letter_spacing": {
        -        "description": "Letter spacing, px.",
        -        "type": "number"
        -      },
        -      "line_height": {
        -        "description": "Line height, px; 0 = the font metrics.",
        -        "type": "number"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0..1.",
        -        "type": "number"
        -      },
        -      "outline_color": {
        -        "description": "Stroke colour.",
        -        "properties": {
        -          "a": {
        -            "description": "Alpha 0..255; 255 opaque.",
        -            "type": "integer"
        -          },
        -          "b": {
        -            "description": "Blue 0..255.",
        -            "type": "integer"
        -          },
        -          "g": {
        -            "description": "Green 0..255.",
        -            "type": "integer"
        -          },
        -          "r": {
        -            "description": "Red 0..255.",
        -            "type": "integer"
        -          }
        -        },
        -        "required": [
        -          "r",
        -          "g",
        -          "b",
        -          "a"
        -        ],
        -        "type": "object"
        -      },
        -      "outline_width": {
        -        "description": "Stroke width, composition px; 0 removes the outline.",
        -        "type": "number"
        -      },
        -      "rotation_deg": {
        -        "description": "Rotation, degrees clockwise.",
        -        "type": "number"
        -      },
        -      "shadow": {
        -        "description": "Drop shadow, or null for none.",
        -        "properties": {
        -          "blur": {
        -            "description": "Blur radius, composition px; 0 is hard-edged.",
        -            "minimum": 0,
        -            "type": "number"
        -          },
        -          "color": {
        -            "description": "Shadow colour.",
        -            "properties": {
        -              "a": {
        -                "description": "Alpha 0..255; 255 opaque.",
        -                "type": "integer"
        -              },
        -              "b": {
        -                "description": "Blue 0..255.",
        -                "type": "integer"
        -              },
        -              "g": {
        -                "description": "Green 0..255.",
        -                "type": "integer"
        -              },
        -              "r": {
        -                "description": "Red 0..255.",
        -                "type": "integer"
        -              }
        -            },
        -            "required": [
        -              "r",
        -              "g",
        -              "b",
        -              "a"
        -            ],
        -            "type": "object"
        -          },
        -          "offset_x": {
        -            "description": "Horizontal offset, composition px.",
        -            "type": "number"
        -          },
        -          "offset_y": {
        -            "description": "Vertical offset, composition px.",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "color",
        -          "offset_x",
        -          "offset_y",
        -          "blur"
        -        ],
        -        "type": [
        -          "object",
        -          "null"
        -        ]
        -      },
        -      "valign": {
        -        "description": "Vertical alignment inside the box.",
        -        "enum": [
        -          "Top",
        -          "Middle",
        -          "Bottom"
        -        ],
        -        "type": "string"
        -      },
        -      "x": {
        -        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        -        "type": "number"
        -      },
        -      "y": {
        -        "description": "Anchor y, composition px (refused in Path mode).",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "kind"
        -    ]
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "anchor_x": {
        -        "description": "Pivot x, fraction of the width (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "anchor_y": {
        -        "description": "Pivot y, fraction of the height (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "fade_in_us": {
        -        "description": "Fade-in length, µs.",
        -        "type": "integer"
        -      },
        -      "fade_out_us": {
        -        "description": "Fade-out length, µs.",
        -        "type": "integer"
        -      },
        -      "flip_h": {
        -        "description": "Mirror horizontally.",
        -        "type": "boolean"
        -      },
        -      "flip_v": {
        -        "description": "Mirror vertically.",
        -        "type": "boolean"
        -      },
        -      "kind": {
        -        "const": "VideoClip",
        -        "description": "Fields of a VideoClip layer."
        -      },
        -      "opacity": {
        -        "description": "Opacity 0..1.",
        -        "type": "number"
        -      },
        -      "rotation_deg": {
        -        "description": "Rotation, degrees clockwise.",
        -        "type": "number"
        -      },
        -      "scale_x": {
        -        "description": "Horizontal scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "scale_y": {
        -        "description": "Vertical scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "speed": {
        -        "description": "Playback rate; 1 = normal.",
        -        "type": "number"
        -      },
        -      "src_in_us": {
        -        "description": "Source in point, µs.",
        -        "type": "integer"
        -      },
        -      "src_out_us": {
        -        "description": "Source out point (exclusive), µs.",
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        -        "type": "number"
        -      },
        -      "y": {
        -        "description": "Anchor y, composition px (refused in Path mode).",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "kind"
        -    ]
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "anchor_x": {
        -        "description": "Pivot x, fraction of the width (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "anchor_y": {
        -        "description": "Pivot y, fraction of the height (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "fade_in_us": {
        -        "description": "Fade-in length, µs.",
        -        "type": "integer"
        -      },
        -      "fade_out_us": {
        -        "description": "Fade-out length, µs.",
        -        "type": "integer"
        -      },
        -      "kind": {
        -        "const": "ImageOverlay",
        -        "description": "Fields of a ImageOverlay layer."
        -      },
        -      "opacity": {
        -        "description": "Opacity 0..1.",
        -        "type": "number"
        -      },
        -      "rotation_deg": {
        -        "description": "Rotation, degrees clockwise.",
        -        "type": "number"
        -      },
        -      "scale_x": {
        -        "description": "Horizontal scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "scale_y": {
        -        "description": "Vertical scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "x": {
        -        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        -        "type": "number"
        -      },
        -      "y": {
        -        "description": "Anchor y, composition px (refused in Path mode).",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "kind"
        -    ]
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "anchor_x": {
        -        "description": "Pivot x, fraction of the width (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "anchor_y": {
        -        "description": "Pivot y, fraction of the height (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "kind": {
        -        "const": "Motif",
        -        "description": "Fields of a Motif layer."
        -      },
        -      "motif_id": {
        -        "description": "Motif id from list_motifs.",
        -        "type": "string"
        -      },
        -      "motif_version": {
        -        "description": "Motif version to bind.",
        -        "type": "integer"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0..1.",
        -        "type": "number"
        -      },
        -      "props": {
        -        "description": "Motif props, matched against its props_schema.",
        -        "type": "object"
        -      },
        -      "rotation_deg": {
        -        "description": "Rotation, degrees clockwise.",
        -        "type": "number"
        -      },
        -      "scale_x": {
        -        "description": "Horizontal scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "scale_y": {
        -        "description": "Vertical scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "src_in_us": {
        -        "description": "Source in point, µs.",
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        -        "type": "number"
        -      },
        -      "y": {
        -        "description": "Anchor y, composition px (refused in Path mode).",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "kind"
        -    ]
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "color": {
        -        "description": "Fill colour.",
        -        "properties": {
        -          "a": {
        -            "description": "Alpha 0..255; 255 opaque.",
        -            "type": "integer"
        -          },
        -          "b": {
        -            "description": "Blue 0..255.",
        -            "type": "integer"
        -          },
        -          "g": {
        -            "description": "Green 0..255.",
        -            "type": "integer"
        -          },
        -          "r": {
        -            "description": "Red 0..255.",
        -            "type": "integer"
        -          }
        -        },
        -        "required": [
        -          "r",
        -          "g",
        -          "b",
        -          "a"
        -        ],
        -        "type": "object"
        -      },
        -      "height": {
        -        "description": "Colour block height, px.",
        -        "type": "integer"
        -      },
        -      "kind": {
        -        "const": "Color",
        -        "description": "Fields of a Color layer."
        -      },
        -      "width": {
        -        "description": "Colour block width, px.",
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "kind"
        -    ]
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "fade_in_us": {
        -        "description": "Fade-in length, µs.",
        -        "type": "integer"
        -      },
        -      "fade_out_us": {
        -        "description": "Fade-out length, µs.",
        -        "type": "integer"
        -      },
        -      "gain_db": {
        -        "description": "Gain, dB; written Static, replacing any keyframes.",
        -        "type": "number"
        -      },
        -      "kind": {
        -        "const": "Audio",
        -        "description": "Fields of a Audio layer."
        -      },
        -      "mute": {
        -        "description": "Silence the clip.",
        -        "type": "boolean"
        -      },
        -      "pan": {
        -        "description": "Stereo pan, -1 (left) .. 1 (right); written Static.",
        -        "type": "number"
        -      },
        -      "role": {
        -        "description": "Mixing bus.",
        -        "enum": [
        -          "dialogue",
        -          "music",
        -          "sfx",
        -          "voiceover"
        -        ],
        -        "type": "string"
        -      },
        -      "src_in_us": {
        -        "description": "Source in point, µs.",
        -        "type": "integer"
        -      },
        -      "src_out_us": {
        -        "description": "Source out point (exclusive), µs.",
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "kind"
        -    ]
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "anchor_x": {
        -        "description": "Pivot x, fraction of the width (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "anchor_y": {
        -        "description": "Pivot y, fraction of the height (0.5 = centre).",
        -        "type": "number"
        -      },
        -      "blend_mode": {
        -        "description": "How the Group composites over what lies below.",
        -        "enum": [
        -          "Normal",
        -          "Multiply",
        -          "Screen",
        -          "Overlay",
        -          "Darken",
        -          "Lighten",
        -          "Add",
        -          "Difference"
        -        ],
        -        "type": "string"
        -      },
        -      "kind": {
        -        "const": "CompositionRef",
        -        "description": "Fields of a CompositionRef layer."
        -      },
        -      "opacity": {
        -        "description": "Opacity 0..1.",
        -        "type": "number"
        -      },
        -      "rotation_deg": {
        -        "description": "Rotation, degrees clockwise.",
        -        "type": "number"
        -      },
        -      "scale_x": {
        -        "description": "Horizontal scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "scale_y": {
        -        "description": "Vertical scale factor; 1 = native size.",
        -        "type": "number"
        -      },
        -      "src_in_us": {
        -        "description": "Source in point, µs.",
        -        "type": "integer"
        -      },
        -      "src_out_us": {
        -        "description": "Source out point (exclusive), µs.",
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        -        "type": "number"
        -      },
        -      "y": {
        -        "description": "Anchor y, composition px (refused in Path mode).",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "kind"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "align": {
        +        "description": "Horizontal alignment inside the box.",
        +        "enum": [
        +          "Left",
        +          "Center",
        +          "Right"
        +        ],
        +        "type": "string"
        +      },
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "box_h": {
        +        "description": "Layout box height, composition px, local (before `scale`). null = auto height. Refused when the layer has no box_w and the patch supplies none.",
        +        "exclusiveMinimum": 0,
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "box_w": {
        +        "description": "Layout box width, composition px, local (before `scale`). null = auto width.",
        +        "exclusiveMinimum": 0,
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "color": {
        +        "description": "Fill colour.",
        +        "properties": {
        +          "a": {
        +            "description": "Alpha 0..255; 255 opaque.",
        +            "type": "integer"
        +          },
        +          "b": {
        +            "description": "Blue 0..255.",
        +            "type": "integer"
        +          },
        +          "g": {
        +            "description": "Green 0..255.",
        +            "type": "integer"
        +          },
        +          "r": {
        +            "description": "Red 0..255.",
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "r",
        +          "g",
        +          "b",
        +          "a"
        +        ],
        +        "type": "object"
        +      },
        +      "content": {
        +        "description": "The text; newlines are honoured.",
        +        "type": "string"
        +      },
        +      "font_family": {
        +        "description": "Font family name.",
        +        "type": "string"
        +      },
        +      "font_size_px": {
        +        "description": "Font size, composition px.",
        +        "type": "number"
        +      },
        +      "font_weight": {
        +        "description": "CSS weight 100..900; 400 regular, 700 bold.",
        +        "type": "integer"
        +      },
        +      "italic": {
        +        "description": "Italic face.",
        +        "type": "boolean"
        +      },
        +      "kind": {
        +        "const": "Text",
        +        "description": "Fields of a Text layer."
        +      },
        +      "letter_spacing": {
        +        "description": "Letter spacing, px.",
        +        "type": "number"
        +      },
        +      "line_height": {
        +        "description": "Line height, px; 0 = the font metrics.",
        +        "type": "number"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "outline_color": {
        +        "description": "Stroke colour.",
        +        "properties": {
        +          "a": {
        +            "description": "Alpha 0..255; 255 opaque.",
        +            "type": "integer"
        +          },
        +          "b": {
        +            "description": "Blue 0..255.",
        +            "type": "integer"
        +          },
        +          "g": {
        +            "description": "Green 0..255.",
        +            "type": "integer"
        +          },
        +          "r": {
        +            "description": "Red 0..255.",
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "r",
        +          "g",
        +          "b",
        +          "a"
        +        ],
        +        "type": "object"
        +      },
        +      "outline_width": {
        +        "description": "Stroke width, composition px; 0 removes the outline.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "shadow": {
        +        "description": "Drop shadow, or null for none.",
        +        "properties": {
        +          "blur": {
        +            "description": "Blur radius, composition px; 0 is hard-edged.",
        +            "minimum": 0,
        +            "type": "number"
        +          },
        +          "color": {
        +            "description": "Shadow colour.",
        +            "properties": {
        +              "a": {
        +                "description": "Alpha 0..255; 255 opaque.",
        +                "type": "integer"
        +              },
        +              "b": {
        +                "description": "Blue 0..255.",
        +                "type": "integer"
        +              },
        +              "g": {
        +                "description": "Green 0..255.",
        +                "type": "integer"
        +              },
        +              "r": {
        +                "description": "Red 0..255.",
        +                "type": "integer"
        +              }
        +            },
        +            "required": [
        +              "r",
        +              "g",
        +              "b",
        +              "a"
        +            ],
        +            "type": "object"
        +          },
        +          "offset_x": {
        +            "description": "Horizontal offset, composition px.",
        +            "type": "number"
        +          },
        +          "offset_y": {
        +            "description": "Vertical offset, composition px.",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "color",
        +          "offset_x",
        +          "offset_y",
        +          "blur"
        +        ],
        +        "type": [
        +          "object",
        +          "null"
        +        ]
        +      },
        +      "valign": {
        +        "description": "Vertical alignment inside the box.",
        +        "enum": [
        +          "Top",
        +          "Middle",
        +          "Bottom"
        +        ],
        +        "type": "string"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "crop": {
        +        "additionalProperties": false,
        +        "description": "Static retained source rectangle in normalized 0..1 coordinates, before transform. x/y are top-left; w/h positive, contained in source. Null resets. Does not change scale or position.",
        +        "properties": {
        +          "h": {
        +            "description": "Height.",
        +            "exclusiveMinimum": 0,
        +            "maximum": 1,
        +            "type": "number"
        +          },
        +          "w": {
        +            "description": "Width.",
        +            "exclusiveMinimum": 0,
        +            "maximum": 1,
        +            "type": "number"
        +          },
        +          "x": {
        +            "description": "Left.",
        +            "maximum": 1,
        +            "minimum": 0,
        +            "type": "number"
        +          },
        +          "y": {
        +            "description": "Top.",
        +            "maximum": 1,
        +            "minimum": 0,
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "x",
        +          "y",
        +          "w",
        +          "h"
        +        ],
        +        "type": [
        +          "object",
        +          "null"
        +        ]
        +      },
        +      "fade_in_us": {
        +        "description": "Fade-in length, µs.",
        +        "type": "integer"
        +      },
        +      "fade_out_us": {
        +        "description": "Fade-out length, µs.",
        +        "type": "integer"
        +      },
        +      "flip_h": {
        +        "description": "Mirror horizontally.",
        +        "type": "boolean"
        +      },
        +      "flip_v": {
        +        "description": "Mirror vertically.",
        +        "type": "boolean"
        +      },
        +      "kind": {
        +        "const": "VideoClip",
        +        "description": "Fields of a VideoClip layer."
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "src_out_us": {
        +        "description": "Source out point (exclusive), µs.",
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "fade_in_us": {
        +        "description": "Fade-in length, µs.",
        +        "type": "integer"
        +      },
        +      "fade_out_us": {
        +        "description": "Fade-out length, µs.",
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "const": "ImageOverlay",
        +        "description": "Fields of a ImageOverlay layer."
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "kind": {
        +        "const": "Motif",
        +        "description": "Fields of a Motif layer."
        +      },
        +      "motif_id": {
        +        "description": "Motif id from list_motifs.",
        +        "type": "string"
        +      },
        +      "motif_version": {
        +        "description": "Motif version to bind.",
        +        "type": "integer"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "props": {
        +        "description": "Motif props, matched against its props_schema.",
        +        "type": "object"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "color": {
        +        "description": "Fill colour.",
        +        "properties": {
        +          "a": {
        +            "description": "Alpha 0..255; 255 opaque.",
        +            "type": "integer"
        +          },
        +          "b": {
        +            "description": "Blue 0..255.",
        +            "type": "integer"
        +          },
        +          "g": {
        +            "description": "Green 0..255.",
        +            "type": "integer"
        +          },
        +          "r": {
        +            "description": "Red 0..255.",
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "r",
        +          "g",
        +          "b",
        +          "a"
        +        ],
        +        "type": "object"
        +      },
        +      "height": {
        +        "description": "Colour block height, px.",
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "const": "Color",
        +        "description": "Fields of a Color layer."
        +      },
        +      "width": {
        +        "description": "Colour block width, px.",
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "fade_in_us": {
        +        "description": "Fade-in length, µs.",
        +        "type": "integer"
        +      },
        +      "fade_out_us": {
        +        "description": "Fade-out length, µs.",
        +        "type": "integer"
        +      },
        +      "gain_db": {
        +        "description": "Gain, dB; written Static, replacing any keyframes.",
        +        "type": "number"
        +      },
        +      "kind": {
        +        "const": "Audio",
        +        "description": "Fields of a Audio layer."
        +      },
        +      "mute": {
        +        "description": "Silence the clip.",
        +        "type": "boolean"
        +      },
        +      "pan": {
        +        "description": "Stereo pan, -1 (left) .. 1 (right); written Static.",
        +        "type": "number"
        +      },
        +      "role": {
        +        "description": "Mixing bus.",
        +        "enum": [
        +          "dialogue",
        +          "music",
        +          "sfx",
        +          "voiceover"
        +        ],
        +        "type": "string"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "src_out_us": {
        +        "description": "Source out point (exclusive), µs.",
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "blend_mode": {
        +        "description": "How the Group composites over what lies below.",
        +        "enum": [
        +          "Normal",
        +          "Multiply",
        +          "Screen",
        +          "Overlay",
        +          "Darken",
        +          "Lighten",
        +          "Add",
        +          "Difference"
        +        ],
        +        "type": "string"
        +      },
        +      "kind": {
        +        "const": "CompositionRef",
        +        "description": "Fields of a CompositionRef layer."
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "src_out_us": {
        +        "description": "Source out point (exclusive), µs.",
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  }
        +]
  2. 14 tool updatesv0.2.2
    • Changedadd_audio_layer1 field changed
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."New value: +"Optional composition check for track_id; mismatch rejects. track_id fixes the composition."
    • Changedadd_color_layer1 field changed
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."New value: +"Optional composition check for track_id; mismatch rejects. track_id fixes the composition."
    • Changedadd_group_layer1 field changed
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."New value: +"Optional composition check for track_id; mismatch rejects. track_id fixes the composition."
    • Changedadd_text_layer1 field changed
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."New value: +"Optional composition check for track_id; mismatch rejects. track_id fixes the composition."
    • Changedadd_video_layer1 field changed
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."New value: +"Optional composition check for track_id; mismatch rejects. track_id fixes the composition."
    • Changedclear_keyframes1 field changed
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
    • Changeddelete_keyframe1 field changed
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
    • Changedget_param_track1 field changed
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
    • Changedrestack_layer4 fields changed
      • addedInput schema / oneOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "anchor_track_id"
        +      ]
        +    },
        +    "required": [
        +      "anchor_layer_id"
        +    ]
        +  },
        +  {
        +    "not": {
        +      "required": [
        +        "anchor_layer_id"
        +      ]
        +    },
        +    "required": [
        +      "anchor_track_id"
        +    ]
        +  }
        +]
      • changedInput schema / properties / anchor_layer_id / description
        Previous value: -"The visual layer to place it against; may sit on a reserved track."New value: +"The visual layer to place it against; supply exactly one of anchor_layer_id / anchor_track_id."
      • addedInput schema / properties / anchor_track_id
        Added value: +{
        +  "description": "A visual track to place it against, including an empty reserved lane. Supply instead of anchor_layer_id.",
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "anchor_layer_id",
        -  "layer_id",
        -  "position"
        -]New value: +[
        +  "layer_id",
        +  "position"
        +]
    • Changedset_extrapolation3 fields changed
      • changedInput schema / properties / after / description
        Previous value: -"After the last key. Hold = the end value; Loop = repeat the cycle; PingPong = alternate cycles reversed; Offset = each cycle adds the last-minus-first delta; Continue = carry the end velocity on as a line."New value: +"After the last key; modes as described by this tool."
      • changedInput schema / properties / before / description
        Previous value: -"Before the first key. Hold = the end value; Loop = repeat the cycle; PingPong = alternate cycles reversed; Offset = each cycle adds the last-minus-first delta; Continue = carry the end velocity on as a line."New value: +"Before the first key; modes as described by this tool."
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
    • Changedset_keyframe1 field changed
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
    • Changedset_param_track1 field changed
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
    • Changedsmooth_keyframes1 field changed
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
    • Changedupdate_keyframe1 field changed
      • changedInput schema / properties / param_key / description
        Previous value: -"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."New value: +"Visual: x/y (XY), path_progress (Path), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text/Color: color; Audio: gain_db, pan; effects[<effect_id>].params[<key>]."
  3. 9 tool updatesv0.2.1
    • Addedanalyze_audio
    • Changedapply_subtitles6 fields changed
      • removedInput schema / properties / body
        Removed value: -{
        -  "description": "Subtitle document body (SRT, ASS, or VTT).",
        -  "type": "string"
        -}
      • addedInput schema / properties / composition_id
        Added value: +{
        +  "description": "Composition to create in — a Group's id from `project://compositions`; omit for the root.",
        +  "type": "string"
        +}
      • removedInput schema / properties / format
        Removed value: -{
        -  "description": "'srt', 'ass', or 'vtt'. Sniffed from body when omitted.",
        -  "type": "string"
        -}
      • addedInput schema / properties / media_id
        Added value: +{
        +  "description": "Subtitle media id.",
        +  "type": "string"
        +}
      • addedInput schema / properties / t_start_us
        Added value: +{
        +  "description": "Where the document's time 0 lands on the timeline; default 0, µs.",
        +  "type": "integer"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "body"
        -]New value: +[
        +  "media_id"
        +]
    • Changedcreate_link1 field changed
      • removedInput schema / properties / label
        Removed value: -{
        -  "description": "Optional name.",
        -  "type": "string"
        -}
    • Addedcreate_project
    • Addedopen_project
    • Changedset_param_track8 fields changed
      • addedInput schema / properties / track / properties / value / items / additionalProperties
        Added value: +false
      • changedInput schema / properties / track / properties / value / items / properties / continuity / description
        Previous value: -"With both sides Free: Smooth keeps their slopes locked equal on write, Broken lets them differ."New value: +"Defaults to Broken. Smooth keeps both Free sides at equal slopes on write."
      • removedInput schema / properties / track / properties / value / items / properties / id
        Removed value: -{
        -  "description": "Key id: an existing one updates that key, a fresh one adds.",
        -  "type": "string"
        -}
      • changedInput schema / properties / track / properties / value / items / properties / in / description
        Previous value: -"Arriving tangent."New value: +"Optional arriving tangent; defaults to identity, Free."
      • changedInput schema / properties / track / properties / value / items / properties / out / description
        Previous value: -"Leaving tangent."New value: +"Optional leaving tangent; defaults to identity, Free."
      • changedInput schema / properties / track / properties / value / items / properties / segment / description
        Previous value: -"Class of the segment LEAVING the key: Spline (reads the tangents) | Hold | Linear | Elastic (dir, amplitude?, period?) | Bounce (dir)."New value: +"Class of the segment LEAVING the key: Spline (reads the tangents) | Hold | Linear | Elastic (dir, amplitude?, period?) | Bounce (dir). Defaults to Linear."
      • changedInput schema / properties / track / properties / value / items / properties / t_us / description
        Previous value: -"Key time, timeline-absolute, µs."New value: +"Key time; timeline-absolute for set_param_track, layer-local for set_position, µs."
      • changedInput schema / properties / track / properties / value / items / required
        Previous value: -[
        -  "id",
        -  "t_us",
        -  "value",
        -  "in",
        -  "out",
        -  "continuity",
        -  "segment"
        -]New value: +[
        +  "t_us",
        +  "value"
        +]
    • Changedset_position23 fields changed
      • addedInput schema / properties / position / properties / path / properties / nodes / items / additionalProperties
        Added value: +false
      • removedInput schema / properties / position / properties / path / properties / nodes / items / properties / id
        Removed value: -{
        -  "description": "Node id, unique and non-empty (yours to mint).",
        -  "type": "string"
        -}
      • changedInput schema / properties / position / properties / path / properties / nodes / items / properties / segment / description
        Previous value: -"Span LEAVING this node: Line, or Cubic (reads the handles)."New value: +"Span LEAVING this node; defaults to Line. Cubic reads the handles."
      • changedInput schema / properties / position / properties / path / properties / nodes / items / properties / tangent_mode / description
        Previous value: -"Corner: handles independent. Smooth: aligned directions, own lengths. Auto: solved from the neighbours on write."New value: +"Defaults to Corner. Smooth aligns handles; Auto solves from neighbours."
      • changedInput schema / properties / position / properties / path / properties / nodes / items / required
        Previous value: -[
        -  "id",
        -  "point",
        -  "in_handle",
        -  "out_handle",
        -  "segment",
        -  "tangent_mode"
        -]New value: +[
        +  "point"
        +]
      • changedInput schema / properties / position / properties / progress / properties / extrapolate / description
        Previous value: -"What the track does outside its keys, per side: Hold | Loop | PingPong | Offset | Continue (see set_extrapolation)."New value: +"Optional {before,after}: Hold/Loop/PingPong/Offset/Continue; Path progress allows the first three. Defaults to Hold/Hold."
      • removedInput schema / properties / position / properties / progress / properties / extrapolate / properties
        Removed value: -{
        -  "after": {
        -    "description": "After the last key.",
        -    "enum": [
        -      "Hold",
        -      "Loop",
        -      "PingPong",
        -      "Offset",
        -      "Continue"
        -    ],
        -    "type": "string"
        -  },
        -  "before": {
        -    "description": "Before the first key.",
        -    "enum": [
        -      "Hold",
        -      "Loop",
        -      "PingPong",
        -      "Offset",
        -      "Continue"
        -    ],
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / position / properties / progress / properties / extrapolate / required
        Removed value: -[
        -  "before",
        -  "after"
        -]
      • changedInput schema / properties / position / properties / progress / properties / mode / description
        Previous value: -"Static holds one number; Keyframed animates the key array."New value: +"Static number or animated keys."
      • changedInput schema / properties / position / properties / progress / properties / value / description
        Previous value: -"Static: the number. Keyframed: the keys, in `set_param_track`'s key shape with layer-local `t_us`."New value: +"Number, or keys with generated IDs (omit id)."
      • addedInput schema / properties / position / properties / progress / properties / value / items
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "continuity": {
        +      "description": "Defaults to Broken.",
        +      "enum": [
        +        "Smooth",
        +        "Broken"
        +      ],
        +      "type": "string"
        +    },
        +    "in": {
        +      "description": "Arriving {x,y,mode}; defaults to identity/Free.",
        +      "type": "object"
        +    },
        +    "out": {
        +      "description": "Leaving {x,y,mode}; defaults to identity/Free.",
        +      "type": "object"
        +    },
        +    "segment": {
        +      "description": "{kind,...} from set_param_track; defaults to Linear.",
        +      "type": "object"
        +    },
        +    "t_us": {
        +      "description": "Layer-local time, µs.",
        +      "type": "integer"
        +    },
        +    "value": {
        +      "description": "Scalar value.",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "t_us",
        +    "value"
        +  ],
        +  "type": "object"
        +}
      • changedInput schema / properties / position / properties / x / properties / extrapolate / description
        Previous value: -"What the track does outside its keys, per side: Hold | Loop | PingPong | Offset | Continue (see set_extrapolation)."New value: +"Optional {before,after}: Hold/Loop/PingPong/Offset/Continue; Path progress allows the first three. Defaults to Hold/Hold."
      • removedInput schema / properties / position / properties / x / properties / extrapolate / properties
        Removed value: -{
        -  "after": {
        -    "description": "After the last key.",
        -    "enum": [
        -      "Hold",
        -      "Loop",
        -      "PingPong",
        -      "Offset",
        -      "Continue"
        -    ],
        -    "type": "string"
        -  },
        -  "before": {
        -    "description": "Before the first key.",
        -    "enum": [
        -      "Hold",
        -      "Loop",
        -      "PingPong",
        -      "Offset",
        -      "Continue"
        -    ],
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / position / properties / x / properties / extrapolate / required
        Removed value: -[
        -  "before",
        -  "after"
        -]
      • changedInput schema / properties / position / properties / x / properties / mode / description
        Previous value: -"Static holds one number; Keyframed animates the key array."New value: +"Static number or animated keys."
      • changedInput schema / properties / position / properties / x / properties / value / description
        Previous value: -"Static: the number. Keyframed: the keys, in `set_param_track`'s key shape with layer-local `t_us`."New value: +"Number, or keys with generated IDs (omit id)."
      • addedInput schema / properties / position / properties / x / properties / value / items
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "continuity": {
        +      "description": "Defaults to Broken.",
        +      "enum": [
        +        "Smooth",
        +        "Broken"
        +      ],
        +      "type": "string"
        +    },
        +    "in": {
        +      "description": "Arriving {x,y,mode}; defaults to identity/Free.",
        +      "type": "object"
        +    },
        +    "out": {
        +      "description": "Leaving {x,y,mode}; defaults to identity/Free.",
        +      "type": "object"
        +    },
        +    "segment": {
        +      "description": "{kind,...} from set_param_track; defaults to Linear.",
        +      "type": "object"
        +    },
        +    "t_us": {
        +      "description": "Layer-local time, µs.",
        +      "type": "integer"
        +    },
        +    "value": {
        +      "description": "Scalar value.",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "t_us",
        +    "value"
        +  ],
        +  "type": "object"
        +}
      • changedInput schema / properties / position / properties / y / properties / extrapolate / description
        Previous value: -"What the track does outside its keys, per side: Hold | Loop | PingPong | Offset | Continue (see set_extrapolation)."New value: +"Optional {before,after}: Hold/Loop/PingPong/Offset/Continue; Path progress allows the first three. Defaults to Hold/Hold."
      • removedInput schema / properties / position / properties / y / properties / extrapolate / properties
        Removed value: -{
        -  "after": {
        -    "description": "After the last key.",
        -    "enum": [
        -      "Hold",
        -      "Loop",
        -      "PingPong",
        -      "Offset",
        -      "Continue"
        -    ],
        -    "type": "string"
        -  },
        -  "before": {
        -    "description": "Before the first key.",
        -    "enum": [
        -      "Hold",
        -      "Loop",
        -      "PingPong",
        -      "Offset",
        -      "Continue"
        -    ],
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / position / properties / y / properties / extrapolate / required
        Removed value: -[
        -  "before",
        -  "after"
        -]
      • changedInput schema / properties / position / properties / y / properties / mode / description
        Previous value: -"Static holds one number; Keyframed animates the key array."New value: +"Static number or animated keys."
      • changedInput schema / properties / position / properties / y / properties / value / description
        Previous value: -"Static: the number. Keyframed: the keys, in `set_param_track`'s key shape with layer-local `t_us`."New value: +"Number, or keys with generated IDs (omit id)."
      • addedInput schema / properties / position / properties / y / properties / value / items
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "continuity": {
        +      "description": "Defaults to Broken.",
        +      "enum": [
        +        "Smooth",
        +        "Broken"
        +      ],
        +      "type": "string"
        +    },
        +    "in": {
        +      "description": "Arriving {x,y,mode}; defaults to identity/Free.",
        +      "type": "object"
        +    },
        +    "out": {
        +      "description": "Leaving {x,y,mode}; defaults to identity/Free.",
        +      "type": "object"
        +    },
        +    "segment": {
        +      "description": "{kind,...} from set_param_track; defaults to Linear.",
        +      "type": "object"
        +    },
        +    "t_us": {
        +      "description": "Layer-local time, µs.",
        +      "type": "integer"
        +    },
        +    "value": {
        +      "description": "Scalar value.",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "t_us",
        +    "value"
        +  ],
        +  "type": "object"
        +}
    • Changedsplit_layer5 fields changed
      • changedInput schema / properties / at_t_us / description
        Previous value: -"Cut point, timeline; strictly inside the layer, µs."New value: +"Interior timeline cuts, µs; snapped, sorted, deduplicated. Any invalid cut rejects all."
      • addedInput schema / properties / at_t_us / items
        Added value: +{
        +  "type": "integer"
        +}
      • addedInput schema / properties / at_t_us / minItems
        Added value: +1
      • changedInput schema / properties / at_t_us / type
        Previous value: -"integer"New value: +"array"
      • changedInput schema / required
        Previous value: -[
        -  "at_t_us",
        -  "layer_id"
        -]New value: +[
        +  "layer_id",
        +  "at_t_us"
        +]
    • Changedupdate_link1 field changed
      • removedInput schema / properties / label
        Removed value: -{
        -  "description": "New label; null clears it.",
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
  4. 120 tool updatesv0.1.9
    • Addedadd_audio_layer
    • Changedadd_color_layer14 fields changed
      • addedInput schema / properties / color / description
        Added value: +"Fill colour."
      • addedInput schema / properties / color / properties / a / description
        Added value: +"Alpha 0..255; 255 opaque."
      • addedInput schema / properties / color / properties / b / description
        Added value: +"Blue 0..255."
      • addedInput schema / properties / color / properties / g / description
        Added value: +"Green 0..255."
      • addedInput schema / properties / color / properties / r / description
        Added value: +"Red 0..255."
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` must belong to (a Group's id from `project://compositions`). The track alone fixes the composition; omit unless you want the mismatch refused."New value: +"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."
      • changedInput schema / properties / composition_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • addedInput schema / properties / height / description
        Added value: +"Block height, px; default 1080."
      • changedInput schema / properties / height / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • addedInput schema / properties / t_end_us / description
        Added value: +"Timeline end (exclusive), µs."
      • addedInput schema / properties / t_start_us / description
        Added value: +"Timeline start, µs."
      • addedInput schema / properties / track_id / description
        Added value: +"Track id."
      • addedInput schema / properties / width / description
        Added value: +"Block width, px; default 1920."
      • changedInput schema / properties / width / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
    • Changedadd_effect3 fields changed
      • addedInput schema / properties / kind / description
        Added value: +"Catalog key: visual kinds on visual layers, audio.* on Audio layers."
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "blur",
        +  "chromakey",
        +  "brightness",
        +  "contrast",
        +  "saturation",
        +  "sharpen",
        +  "audio.denoise"
        +]
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
    • Changedadd_group_layer4 fields changed
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` must belong to (a Group's id from `project://compositions`). The track alone fixes the composition; omit unless you want the mismatch refused."New value: +"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."
      • changedInput schema / properties / composition_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • addedInput schema / properties / t_start_us / description
        Added value: +"Timeline start, µs."
      • addedInput schema / properties / track_id / description
        Added value: +"Track id."
    • Addedadd_group_members
    • Changedadd_marker12 fields changed
      • changedInput schema / properties / anchor_layer_id / description
        Previous value: -"Clip the new marker should follow — a layer of the SAME composition carrying a source window (VideoClip, Audio, Group). The mark is born tied to the source instant `t_us` lands on, exactly as attach_marker would tie it afterwards, and is refused for the same three reasons; a refusal creates no marker at all. Omit for a marker fixed to the timeline."New value: +"Clip the marker should follow — a layer of the same composition with a source window (VideoClip, Audio, Group). Tied as `set_marker_anchor` would tie it, refused for the same reasons (no marker is created). Omit for a fixed marker."
      • changedInput schema / properties / anchor_layer_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • addedInput schema / properties / color / description
        Added value: +"Marker colour."
      • addedInput schema / properties / color / properties / a / description
        Added value: +"Alpha 0..255; 255 opaque."
      • addedInput schema / properties / color / properties / b / description
        Added value: +"Blue 0..255."
      • addedInput schema / properties / color / properties / g / description
        Added value: +"Green 0..255."
      • addedInput schema / properties / color / properties / r / description
        Added value: +"Red 0..255."
      • changedInput schema / properties / composition_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • addedInput schema / properties / end_t_us / description
        Added value: +"Region end, timeline; omit for a point marker, µs."
      • changedInput schema / properties / end_t_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • addedInput schema / properties / label / description
        Added value: +"Short name shown on the marker lane."
      • addedInput schema / properties / t_us / description
        Added value: +"Marker time, timeline, µs."
    • Removedadd_motif
    • Addedadd_motif_layer
    • Addedadd_text_layer
    • Changedadd_track2 fields changed
      • changedInput schema / properties / composition_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • changedInput schema / properties / label / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
    • Changedadd_transition6 fields changed
      • addedInput schema / properties / direction / description
        Added value: +"Motion direction. Required for Wipe / Slide, refused for Crossfade."
      • addedInput schema / properties / duration_us / description
        Added value: +"Transition length, µs."
      • addedInput schema / properties / from_layer_id / description
        Added value: +"Outgoing layer — the one that ends at the cut."
      • addedInput schema / properties / kind / description
        Added value: +"Default Crossfade."
      • changedInput schema / properties / placement / description
        Previous value: -"Where the overlap comes from. 'overlap' (default): the incoming layer moves left; both trimmed ranges preserved. 'extend': the outgoing layer borrows tail media; positions untouched."New value: +"'overlap' (default): the incoming layer moves left, trimmed ranges preserved. 'extend': the outgoing layer borrows tail media, positions untouched."
      • addedInput schema / properties / to_layer_id / description
        Added value: +"Incoming layer — the one that starts at the cut."
    • Changedadd_video_layer9 fields changed
      • changedInput schema / properties / composition_id / description
        Previous value: -"Optional cross-check: the composition `track_id` must belong to (a Group's id from `project://compositions`). The track alone fixes the composition; omit unless you want the mismatch refused."New value: +"Optional cross-check: the composition `track_id` belongs to; refused on mismatch. The track alone fixes the composition."
      • changedInput schema / properties / composition_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • addedInput schema / properties / media_id / description
        Added value: +"Media id."
      • addedInput schema / properties / src_in_us / description
        Added value: +"Source in point, µs. Required for Video; ignored for an Image."
      • addedInput schema / properties / src_out_us / description
        Added value: +"Source out point (exclusive), µs. Required for Video; ignored for an Image."
      • addedInput schema / properties / t_end_us / description
        Added value: +"Timeline end (exclusive), µs."
      • addedInput schema / properties / t_start_us / description
        Added value: +"Timeline start, µs."
      • addedInput schema / properties / track_id / description
        Added value: +"Track id."
      • changedInput schema / required
        Previous value: -[
        -  "media_id",
        -  "src_in_us",
        -  "src_out_us",
        -  "t_end_us",
        -  "t_start_us",
        -  "track_id"
        -]New value: +[
        +  "media_id",
        +  "t_end_us",
        +  "t_start_us",
        +  "track_id"
        +]
    • Changedanalyze_clip7 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / properties / min_shot_us / format
        Removed value: -"int64"
      • changedInput schema / properties / min_shot_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • changedInput schema / properties / passes / type
        Previous value: -[
        -  "array",
        -  "null"
        -]New value: +"array"
      • removedInput schema / properties / sensitivity / format
        Removed value: -"float"
      • changedInput schema / properties / sensitivity / type
        Previous value: -[
        -  "number",
        -  "null"
        -]New value: +"number"
      • removedInput schema / title
        Removed value: -"AnalyzeClipArgs"
    • Changedapply_subtitles7 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / format / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • removedInput schema / properties / t_end_us
        Removed value: -{
        -  "description": "IGNORED — cue timings come from the body, not the timeline envelope.\nKept for wire-schema stability; do not remove.",
        -  "format": "int64",
        -  "type": "integer"
        -}
      • removedInput schema / properties / t_start_us
        Removed value: -{
        -  "description": "IGNORED — cue timings come from the body, not the timeline envelope.\nKept for wire-schema stability; do not remove.",
        -  "format": "int64",
        -  "type": [
        -    "integer",
        -    "null"
        -  ]
        -}
      • removedInput schema / properties / track_id
        Removed value: -{
        -  "description": "IGNORED — the lane is the packing's to pick: cues land on the caption\ntracks already there where they have room (ADR 0070). Kept for\nwire-schema stability; do not remove.",
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • changedInput schema / required
        Previous value: -[
        -  "body",
        -  "t_end_us"
        -]New value: +[
        +  "body"
        +]
      • removedInput schema / title
        Removed value: -"ApplySubtitlesArgs"
    • Addedapply_transcripts
    • Removedattach_marker
    • Changedauto_split_by_shot5 fields changed
      • addedInput schema / properties / drop_short / description
        Added value: +"Also delete segments shorter than min_shot_us, with the overlapping members of their link. Default false."
      • changedInput schema / properties / drop_short / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
      • addedInput schema / properties / layer_id / description
        Added value: +"The VideoClip to split."
      • addedInput schema / properties / min_shot_us / description
        Added value: +"Shortest shot to keep; default 500000, µs."
      • changedInput schema / properties / min_shot_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
    • Changedbegin_agent_session1 field changed
      • addedInput schema / properties / reason / description
        Added value: +"What this work session is for; shown to the user beside the busy badge."
    • Removedcheckpoint
    • Changedclear_keyframes6 fields changed
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / param_key / anyOf
        Added value: +[
        +  {
        +    "enum": [
        +      "x",
        +      "y",
        +      "path_progress",
        +      "scale_x",
        +      "scale_y",
        +      "rotation_deg",
        +      "anchor_x",
        +      "anchor_y",
        +      "opacity",
        +      "color",
        +      "gain_db",
        +      "pan"
        +    ]
        +  },
        +  {
        +    "pattern": "^effects\\[[0-9a-fA-F-]{36}\\]\\.params\\[[A-Za-z0-9_]+\\]$"
        +  }
        +]
      • addedInput schema / properties / param_key / description
        Added value: +"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."
      • changedInput schema / properties / value / description
        Previous value: -"Typed by `param_key`: a number for every scalar param (x, y, path_progress, scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity, gain_db, pan, effect params); an {r,g,b,a} colour (integers 0..255) for \"color\" — the Text and Color layers' colour. Path mode rejects independent x/y writes; use path_progress (a fraction, not a percentage); XY mode has no path_progress. A mismatch is refused naming the type the param takes."New value: +"The value to hold, typed by `param_key`; omit for the first keyframe's value."
      • removedInput schema / properties / value / oneOf
        Removed value: -[
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "properties": {
        -      "a": {
        -        "type": "integer"
        -      },
        -      "b": {
        -        "type": "integer"
        -      },
        -      "g": {
        -        "type": "integer"
        -      },
        -      "r": {
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "r",
        -      "g",
        -      "b",
        -      "a"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • changedInput schema / properties / value / type
        Previous value: -[
        -  "number",
        -  "object",
        -  "null"
        -]New value: +[
        +  "number",
        +  "object"
        +]
    • Changedcompare_frames11 fields changed
      • removedInput schema / $defs
        Removed value: -{
        -  "FrameRef": {
        -    "description": "One side of a `compare_frames` pair. `#[schemars(skip)]` on the injected\n`layer` / `media` keeps each side's ADVERTISED schema exactly\n`{ layer_id, t_us }`; serde still deserializes the host-injected slice.",
        -    "properties": {
        -      "layer_id": {
        -        "description": "Target VideoClip layer id.",
        -        "type": "string"
        -      },
        -      "t_us": {
        -        "description": "SOURCE-ABSOLUTE timestamp (microseconds) of the frame to sample — the\nsame coordinate space as `media://{id}/frame/<t_us>` and the\n`keyframe_t_us` / `t_*_us` that `analyze_clip` returns, so a shot cover\nframe can be fed straight in.",
        -        "format": "int64",
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "layer_id",
        -      "t_us"
        -    ],
        -    "type": "object"
        -  }
        -}
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / properties / a / $ref
        Removed value: -"#/$defs/FrameRef"
      • addedInput schema / properties / a / properties
        Added value: +{
        +  "layer_id": {
        +    "description": "Target VideoClip layer id.",
        +    "type": "string"
        +  },
        +  "t_us": {
        +    "description": "SOURCE-ABSOLUTE microseconds of the frame to sample (the space\n`analyze_clip`'s `keyframe_t_us` uses).",
        +    "type": "integer"
        +  }
        +}
      • addedInput schema / properties / a / required
        Added value: +[
        +  "layer_id",
        +  "t_us"
        +]
      • addedInput schema / properties / a / type
        Added value: +"object"
      • removedInput schema / properties / b / $ref
        Removed value: -"#/$defs/FrameRef"
      • addedInput schema / properties / b / properties
        Added value: +{
        +  "layer_id": {
        +    "description": "Target VideoClip layer id.",
        +    "type": "string"
        +  },
        +  "t_us": {
        +    "description": "SOURCE-ABSOLUTE microseconds of the frame to sample (the space\n`analyze_clip`'s `keyframe_t_us` uses).",
        +    "type": "integer"
        +  }
        +}
      • addedInput schema / properties / b / required
        Added value: +[
        +  "layer_id",
        +  "t_us"
        +]
      • addedInput schema / properties / b / type
        Added value: +"object"
      • removedInput schema / title
        Removed value: -"CompareFramesArgs"
    • Removedcompositions_delete
    • Addedcorrect_caption_text
    • Addedcreate_checkpoint
    • Addedcreate_group
    • Addedcreate_link
    • Addeddelete_checkpoint
    • Addeddelete_composition
    • Addeddelete_effect
    • Addeddelete_keyframe
    • Removeddelete_layer
    • Addeddelete_layers
    • Addeddelete_link
    • Addeddelete_marker
    • Addeddelete_media
    • Changeddelete_motif3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedInput schema / description
        Removed value: -"Shared single-id arg for `get_motif_source` + `delete_motif`."
      • removedInput schema / title
        Removed value: -"MotifIdArgs"
    • Addeddelete_track
    • Addeddelete_transition
    • Changeddescribe_clip21 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / properties / backend / default
        Removed value: -null
      • changedInput schema / properties / backend / description
        Previous value: -"Optional STRICT backend override: `\"qwen3_vl\"` | `\"minicpm_v\"` |\n`\"byo_endpoint\"`. When set, that engine serves the request or the call\nerrors naming its exact gap — it never substitutes another engine, so an\nexplicit local choice can never leak frames over the network.\nWhen omitted, selection is preference then availability. Unknown → rejected."New value: +"Strict engine override: `\"qwen3_vl\"` | `\"minicpm_v\"` | `\"byo_endpoint\"`.\nThat engine serves or the call errors; nothing is substituted. Omitted:\nthe user's preferred engine, then availability."
      • changedInput schema / properties / backend / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • removedInput schema / properties / focus / default
        Removed value: -null
      • changedInput schema / properties / focus / description
        Previous value: -"Prompt focus: `\"general\"` or `\"shot-type\"` (biases `tags` toward shot\ntype / camera). Defaults to the app's Video-understanding setting, which\nthe host injects when this is omitted; with no host, `\"general\"`. Part of\nthe cache key."New value: +"`\"general\"` or `\"shot-type\"` (biases `tags` toward shot type / camera).\nDefault: the app's setting, else `\"general\"`. Cache key."
      • changedInput schema / properties / focus / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • removedInput schema / properties / fps / default
        Removed value: -null
      • changedInput schema / properties / fps / description
        Previous value: -"Frames sampled per second across the window. Higher = finer temporal\ndetail at more cost; capped so the frame set fits the model's context.\nDefaults to the app's Video-understanding setting, which the host injects\nwhen this is omitted; with no host, 1.0. Part of the cache key."New value: +"Frames sampled per second (higher = finer, costlier; capped to the\nmodel's context). Default: the app's setting, else 1.0. Cache key."
      • removedInput schema / properties / fps / format
        Removed value: -"double"
      • changedInput schema / properties / fps / type
        Previous value: -[
        -  "number",
        -  "null"
        -]New value: +"number"
      • removedInput schema / properties / language / default
        Removed value: -null
      • changedInput schema / properties / language / description
        Previous value: -"Language the `text` and `tags` come back in, as a BCP-47 tag\n(`\"en-US\"`, `\"zh-CN\"`, `\"ja\"`, …). Defaults to the app's UI language,\nwhich the host injects when this is omitted; with no host, `\"en-US\"`.\nPart of the cache key — a description in another language is a different\ndescription, not a translation of this one."New value: +"BCP-47 tag the `text` and `tags` come back in (`\"en-US\"`, `\"zh-CN\"`,\n`\"ja\"`). Default: the app's UI language. Cache key."
      • changedInput schema / properties / language / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • removedInput schema / properties / t_end_us / default
        Removed value: -null
      • removedInput schema / properties / t_end_us / format
        Removed value: -"int64"
      • changedInput schema / properties / t_end_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / properties / t_start_us / default
        Removed value: -null
      • removedInput schema / properties / t_start_us / format
        Removed value: -"int64"
      • changedInput schema / properties / t_start_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / title
        Removed value: -"DescribeClipArgs"
    • Removeddetach_marker
    • Changeddetect_pauses9 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / bridge_us / description
        Previous value: -"A loud run shorter than this INSIDE a quiet run does not end the pause,\nin microseconds. Default 80000 (80ms) — long enough to swallow a click,\na cough or lip noise, short enough that no syllable fits. Must be ≥ 0\nand strictly below `min_pause_us`."New value: +"A loud run shorter than this (µs) inside a quiet run does not end the\npause. Default 80000 (80ms). Must be ≥ 0 and below `min_pause_us`."
      • removedInput schema / properties / bridge_us / format
        Removed value: -"int64"
      • changedInput schema / properties / bridge_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / properties / min_pause_us / format
        Removed value: -"int64"
      • changedInput schema / properties / min_pause_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / properties / threshold_amp / format
        Removed value: -"float"
      • changedInput schema / properties / threshold_amp / type
        Previous value: -[
        -  "number",
        -  "null"
        -]New value: +"number"
      • removedInput schema / title
        Removed value: -"DetectPausesArgs"
    • Changeddry_run2 fields changed
      • addedInput schema / properties / operations / description
        Added value: +"The edits to rehearse, in order."
      • changedInput schema / properties / operations / items / description
        Previous value: -"OperationSpec: {\"kind\": \"add_color_layer\" | \"add_video_layer\" | \"update_layer\" | \"update_layer_params\" | \"move_layer\" | \"split_layer\" | \"delete_layer\" | \"add_transition\", ...that tool's snake_case args (add_transition: the transition kind rides as \"transition_kind\" since \"kind\" names the operation, and it also takes \"placement\": \"overlap\" | \"extend\")}."New value: +"{ kind: <one of the supported tool names>, ...that tool's args }. For add_transition the transition kind rides as `transition_kind` (plus optional `placement`)."
    • Removedduplicate_layer
    • Changedend_agent_session1 field changed
      • addedInput schema / properties / force
        Added value: +{
        +  "description": "End another connection's session too. Default false.",
        +  "type": "boolean"
        +}
    • Addedexport_captions
    • Changedextract_clip_audio8 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / properties / t_end_us / default
        Removed value: -null
      • removedInput schema / properties / t_end_us / format
        Removed value: -"int64"
      • changedInput schema / properties / t_end_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / properties / t_start_us / default
        Removed value: -null
      • removedInput schema / properties / t_start_us / format
        Removed value: -"int64"
      • changedInput schema / properties / t_start_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / title
        Removed value: -"ExtractClipAudioArgs"
    • Removedfit_composition_to_layers
    • Changedget_motif_source3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedInput schema / description
        Removed value: -"Shared single-id arg for `get_motif_source` + `delete_motif`."
      • removedInput schema / title
        Removed value: -"MotifIdArgs"
    • Changedget_param_track3 fields changed
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / param_key / anyOf
        Added value: +[
        +  {
        +    "enum": [
        +      "x",
        +      "y",
        +      "path_progress",
        +      "scale_x",
        +      "scale_y",
        +      "rotation_deg",
        +      "anchor_x",
        +      "anchor_y",
        +      "opacity",
        +      "color",
        +      "gain_db",
        +      "pan"
        +    ]
        +  },
        +  {
        +    "pattern": "^effects\\[[0-9a-fA-F-]{36}\\]\\.params\\[[A-Za-z0-9_]+\\]$"
        +  }
        +]
      • addedInput schema / properties / param_key / description
        Added value: +"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."
    • Removedgroups_add_members
    • Removedgroups_create
    • Removedgroups_rename
    • Removedgroups_ungroup
    • Changedimport_media2 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / title
        Removed value: -"ImportMediaArgs"
    • Changedinstall_motif5 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • changedInput schema / properties / mode / description
        Previous value: -"\"new\" (publish under the draft's own id) or \"update\" (republish over the draft's recorded target; fails if the draft has no target)."New value: +"\"new\" (publish under the draft's own id) or \"update\" (republish over `target_id`, else the draft's recorded target)."
      • addedInput schema / properties / mode / enum
        Added value: +[
        +  "new",
        +  "update"
        +]
      • addedInput schema / properties / target_id
        Added value: +{
        +  "description": "For mode \"update\": the installed Motif to republish over. Omit to use the target the draft recorded (`write_motif_draft { from }`).",
        +  "type": "string"
        +}
      • removedInput schema / title
        Removed value: -"InstallMotifArgs"
    • Addedjump_to
    • Removedlinks_add_members
    • Removedlinks_create
    • Removedlinks_dissolve
    • Removedlinks_remove_members
    • Removedlinks_rename
    • Changedlist_motifs4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedInput schema / description
        Removed value: -"Empty arg shape for tools that take no parameters. The dispatch table deserializes `{}` (or any object) into this; `schemars` advertises it as an empty object schema."
      • addedInput schema / properties
        Added value: +{}
      • removedInput schema / title
        Removed value: -"EmptyArgs"
    • Removedlock_history
    • Addedmerge_captions
    • Changedmove_effect3 fields changed
      • addedInput schema / properties / effect_id / description
        Added value: +"Effect id."
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / new_index / description
        Added value: +"Target position in the chain; 0 is applied first."
    • Changedmove_layer5 fields changed
      • addedInput schema / properties / escape_link / description
        Added value: +"Act on this layer alone, leaving its link partners in place. Default false."
      • changedInput schema / properties / escape_link / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / new_t_start_us / description
        Added value: +"New timeline start, µs."
      • addedInput schema / properties / new_track_id / description
        Added value: +"Destination track; the current one to move in time only."
    • Changedmove_layers_to_composition2 fields changed
      • changedInput schema / properties / to_track_id / description
        Previous value: -"Destination lane: a lane id (a locked or occupied one REFUSES), \"spawn\" for a fresh lane at the top of the z-stack, or omit for the per-source-track preference, which bounces."New value: +"A lane id (locked or occupied REFUSES), \"spawn\" for a fresh top lane, or omit to bounce to the nearest free lane."
      • changedInput schema / properties / to_track_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
    • Changedmove_track2 fields changed
      • addedInput schema / properties / new_position / description
        Added value: +"Target index in the stack; 0 is the bottom."
      • addedInput schema / properties / track_id / description
        Added value: +"Track id."
    • Changedpaste_layers4 fields changed
      • addedInput schema / properties / t_offset_us
        Added value: +{
        +  "description": "Start of the seed's clone relative to the seed's own start, so `t_offset_us` shifts every clone by that much. Mutually exclusive with `t_start_us`.",
        +  "type": "integer"
        +}
      • changedInput schema / properties / t_start_us / description
        Previous value: -"Start time of the seed's clone; the other clones keep their offsets from it."New value: +"Absolute start time of the seed's clone; the other clones keep their offsets from it. Mutually exclusive with `t_offset_us`."
      • changedInput schema / properties / target_track_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • changedInput schema / required
        Previous value: -[
        -  "layer_ids",
        -  "t_start_us"
        -]New value: +[
        +  "layer_ids"
        +]
    • Changedping3 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / description
        Removed value: -"Empty arg shape for tools that take no parameters. The dispatch table\ndeserializes `{}` (or any object) into this; `schemars` advertises it as an\nempty object schema."
      • removedInput schema / title
        Removed value: -"EmptyArgs"
    • Changedpreview_motif_draft14 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • changedInput schema / properties / height / description
        Previous value: -"Optional render height (default = the motif's manifest height)."New value: +"Render height; default the motif's manifest height."
      • removedInput schema / properties / height / format
        Removed value: -"uint32"
      • changedInput schema / properties / height / minimum
        Previous value: -0New value: +1
      • changedInput schema / properties / height / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • changedInput schema / properties / props / description
        Previous value: -"Props (JSON object); `{}` uses the manifest defaults."New value: +"Props; omitted or `{}` uses the manifest defaults."
      • changedInput schema / properties / t_sec / description
        Previous value: -"Content time in seconds to render (e.g. 0 = first frame)."New value: +"Content time in seconds to render (0 = first frame)."
      • removedInput schema / properties / t_sec / format
        Removed value: -"double"
      • changedInput schema / properties / width / description
        Previous value: -"Optional render width (default = the motif's manifest width)."New value: +"Render width; default the motif's manifest width."
      • removedInput schema / properties / width / format
        Removed value: -"uint32"
      • changedInput schema / properties / width / minimum
        Previous value: -0New value: +1
      • changedInput schema / properties / width / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • changedInput schema / required
        Previous value: -[
        -  "id",
        -  "props",
        -  "t_sec"
        -]New value: +[
        +  "id",
        +  "t_sec"
        +]
      • removedInput schema / title
        Removed value: -"PreviewMotifDraftArgs"
    • Addedread_project
    • Removedremove_effect
    • Removedremove_keyframe
    • Removedremove_marker
    • Removedremove_media
    • Changedremove_pauses6 fields changed
      • removedInput schema / properties / min_pause_us / format
        Removed value: -"int64"
      • changedInput schema / properties / min_pause_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • changedInput schema / properties / pad_us / description
        Previous value: -"How much of each pause to KEEP on EACH side, in microseconds. Default 100000 (0.1 s), which is what stops a cut from clipping soft word onsets; pass 0 to erase each pause whole. Must be >= 0, and 2 x pad_us must be strictly less than min_pause_us or nothing would be cut."New value: +"Microseconds of each pause KEPT on each side. Default 100000; 0 erases each pause whole. Must satisfy 2 * pad_us < min_pause_us."
      • removedInput schema / properties / pad_us / format
        Removed value: -"int64"
      • changedInput schema / properties / pad_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • changedInput schema / properties / threshold_amp / type
        Previous value: -[
        -  "number",
        -  "null"
        -]New value: +"number"
    • Removedremove_track
    • Removedremove_transition
    • Addedrename_composition
    • Changedrename_track1 field changed
      • addedInput schema / properties / track_id / description
        Added value: +"Track id."
    • Changedrestore_checkpoint1 field changed
      • addedInput schema / properties / checkpoint_id / description
        Added value: +"Checkpoint id."
    • Addedrestyle_captions
    • Removedretime_keyframe
    • Changedripple_delete_gap3 fields changed
      • addedInput schema / properties / end_us / description
        Added value: +"Gap end (exclusive), timeline, µs."
      • addedInput schema / properties / start_us / description
        Added value: +"Gap start, timeline, µs."
      • addedInput schema / properties / track_id / description
        Added value: +"The track the gap is on."
    • Removedripple_delete_layers
    • Addedseparate_audio_to_new_track
    • Removedset_composition
    • Changedset_extrapolation5 fields changed
      • changedInput schema / properties / after / description
        Previous value: -"Hold = the end value (the clamp); Loop = repeat the cycle from the first key (a visible jump when first ≠ last — nothing bridges it); PingPong = odd cycles run backwards; Offset = each cycle adds the last-minus-first delta; Continue = carry the last segment's end velocity on as a line (zero after a Hold or procedural segment)."New value: +"After the last key. Hold = the end value; Loop = repeat the cycle; PingPong = alternate cycles reversed; Offset = each cycle adds the last-minus-first delta; Continue = carry the end velocity on as a line."
      • changedInput schema / properties / before / description
        Previous value: -"Hold = the end value (the clamp); Loop = repeat the cycle from the first key (a visible jump when first ≠ last — nothing bridges it); PingPong = odd cycles run backwards; Offset = each cycle adds the last-minus-first delta; Continue = carry the last segment's end velocity on as a line (zero after a Hold or procedural segment)."New value: +"Before the first key. Hold = the end value; Loop = repeat the cycle; PingPong = alternate cycles reversed; Offset = each cycle adds the last-minus-first delta; Continue = carry the end velocity on as a line."
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / param_key / anyOf
        Added value: +[
        +  {
        +    "enum": [
        +      "x",
        +      "y",
        +      "path_progress",
        +      "scale_x",
        +      "scale_y",
        +      "rotation_deg",
        +      "anchor_x",
        +      "anchor_y",
        +      "opacity",
        +      "color",
        +      "gain_db",
        +      "pan"
        +    ]
        +  },
        +  {
        +    "pattern": "^effects\\[[0-9a-fA-F-]{36}\\]\\.params\\[[A-Za-z0-9_]+\\]$"
        +  }
        +]
      • addedInput schema / properties / param_key / description
        Added value: +"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."
    • Addedset_history_lock
    • Changedset_keyframe7 fields changed
      • addedInput schema / properties / interp / properties / kind / description
        Added value: +"Easing kind of the segment leaving the key."
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / param_key / anyOf
        Added value: +[
        +  {
        +    "enum": [
        +      "x",
        +      "y",
        +      "path_progress",
        +      "scale_x",
        +      "scale_y",
        +      "rotation_deg",
        +      "anchor_x",
        +      "anchor_y",
        +      "opacity",
        +      "color",
        +      "gain_db",
        +      "pan"
        +    ]
        +  },
        +  {
        +    "pattern": "^effects\\[[0-9a-fA-F-]{36}\\]\\.params\\[[A-Za-z0-9_]+\\]$"
        +  }
        +]
      • addedInput schema / properties / param_key / description
        Added value: +"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."
      • addedInput schema / properties / t_us / description
        Added value: +"Key time, timeline-absolute, µs."
      • changedInput schema / properties / value / description
        Previous value: -"Typed by `param_key`: a number for every scalar param (x, y, path_progress, scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity, gain_db, pan, effect params); an {r,g,b,a} colour (integers 0..255) for \"color\" — the Text and Color layers' colour. Path mode rejects independent x/y writes; use path_progress (a fraction, not a percentage); XY mode has no path_progress. A mismatch is refused naming the type the param takes."New value: +"Typed by `param_key`: a number for scalar params (x, y, path_progress, scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity, gain_db, pan, effect params), {r,g,b,a} (0..255) for \"color\". Path mode takes path_progress (a fraction) instead of x/y."
      • removedInput schema / properties / value / oneOf
        Removed value: -[
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "properties": {
        -      "a": {
        -        "type": "integer"
        -      },
        -      "b": {
        -        "type": "integer"
        -      },
        -      "g": {
        -        "type": "integer"
        -      },
        -      "r": {
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "r",
        -      "g",
        -      "b",
        -      "a"
        -    ],
        -    "type": "object"
        -  }
        -]
    • Removedset_keyframe_easing
    • Removedset_keyframe_tangents
    • Changedset_layers_enabled2 fields changed
      • addedInput schema / properties / enabled / description
        Added value: +"true shows, false hides — preview and export alike."
      • addedInput schema / properties / layer_ids / description
        Added value: +"The layers to show or hide."
    • Addedset_marker_anchor
    • Changedset_param_track22 fields changed
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / param_key / anyOf
        Added value: +[
        +  {
        +    "enum": [
        +      "x",
        +      "y",
        +      "path_progress",
        +      "scale_x",
        +      "scale_y",
        +      "rotation_deg",
        +      "anchor_x",
        +      "anchor_y",
        +      "opacity",
        +      "color",
        +      "gain_db",
        +      "pan"
        +    ]
        +  },
        +  {
        +    "pattern": "^effects\\[[0-9a-fA-F-]{36}\\]\\.params\\[[A-Za-z0-9_]+\\]$"
        +  }
        +]
      • addedInput schema / properties / param_key / description
        Added value: +"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."
      • changedInput schema / properties / track / description
        Previous value: -"An animation track: {\"mode\":\"Static\",\"value\":v} or {\"mode\":\"Keyframed\",\"value\":[{id, t_us, value, in, out, continuity, segment}, ...],\"extrapolate\":{before, after}}. Values are typed by `param_key` — a number, or {r,g,b,a} (integers 0..255) for \"color\". A segment's easing is the LEFT key's segment + out and the RIGHT key's in; each side's x is within [0, 1]. `extrapolate` defaults to Hold/Hold when omitted."New value: +"An animation track: {\"mode\":\"Static\",\"value\":v} or {\"mode\":\"Keyframed\",\"value\":[keyframes],\"extrapolate\":{before, after}} (Hold/Hold when omitted). Values are typed by `param_key` — a number, or {r,g,b,a} (integers 0..255) for \"color\"."
      • changedInput schema / properties / track / properties / extrapolate / description
        Previous value: -"What the track does outside its key range, per side (before the first key / after the last). The period is last.t − first.t; a single-key track never extrapolates."New value: +"What the track does outside its keys, per side: Hold | Loop | PingPong | Offset | Continue (see set_extrapolation)."
      • changedInput schema / properties / track / properties / extrapolate / properties / after / description
        Previous value: -"Hold = the end value (the clamp); Loop = repeat the cycle from the first key (a visible jump when first ≠ last — nothing bridges it); PingPong = odd cycles run backwards; Offset = each cycle adds the last-minus-first delta; Continue = carry the last segment's end velocity on as a line (zero after a Hold or procedural segment)."New value: +"After the last key."
      • changedInput schema / properties / track / properties / extrapolate / properties / before / description
        Previous value: -"Hold = the end value (the clamp); Loop = repeat the cycle from the first key (a visible jump when first ≠ last — nothing bridges it); PingPong = odd cycles run backwards; Offset = each cycle adds the last-minus-first delta; Continue = carry the last segment's end velocity on as a line (zero after a Hold or procedural segment)."New value: +"Before the first key."
      • addedInput schema / properties / track / properties / mode / description
        Added value: +"Static holds one value; Keyframed animates the key array."
      • addedInput schema / properties / track / properties / value / items / properties / id / description
        Added value: +"Key id: an existing one updates that key, a fresh one adds."
      • changedInput schema / properties / track / properties / value / items / properties / in / description
        Previous value: -"One side of a key: a control point in the owning segment's unit square (x = fraction of the segment's time span, y = fraction of its value span). `in` is the arriving cubic's second control point as stored (un-mirrored). mode \"Auto\" = re-solved on every write (monotone, no overshoot), \"Free\" = authored."New value: +"Arriving tangent."
      • addedInput schema / properties / track / properties / value / items / properties / in / properties / mode / description
        Added value: +"Auto: solved on every write. Free: as authored."
      • addedInput schema / properties / track / properties / value / items / properties / in / properties / x / description
        Added value: +"Fraction of the segment's time span, 0..1."
      • addedInput schema / properties / track / properties / value / items / properties / in / properties / y / description
        Added value: +"Fraction of the segment's value span; may overshoot."
      • changedInput schema / properties / track / properties / value / items / properties / out / description
        Previous value: -"One side of a key: a control point in the owning segment's unit square (x = fraction of the segment's time span, y = fraction of its value span). `in` is the arriving cubic's second control point as stored (un-mirrored). mode \"Auto\" = re-solved on every write (monotone, no overshoot), \"Free\" = authored."New value: +"Leaving tangent."
      • addedInput schema / properties / track / properties / value / items / properties / out / properties / mode / description
        Added value: +"Auto: solved on every write. Free: as authored."
      • addedInput schema / properties / track / properties / value / items / properties / out / properties / x / description
        Added value: +"Fraction of the segment's time span, 0..1."
      • addedInput schema / properties / track / properties / value / items / properties / out / properties / y / description
        Added value: +"Fraction of the segment's value span; may overshoot."
      • changedInput schema / properties / track / properties / value / items / properties / segment / description
        Previous value: -"Class of the segment LEAVING a key: {\"kind\":\"Spline\"} (its cubic is this key's out and the next key's in) | {\"kind\":\"Hold\"} | {\"kind\":\"Linear\"} | {\"kind\":\"Elastic\",\"dir\",amplitude?,period?} | {\"kind\":\"Bounce\",\"dir\"}."New value: +"Class of the segment LEAVING the key: Spline (reads the tangents) | Hold | Linear | Elastic (dir, amplitude?, period?) | Bounce (dir)."
      • addedInput schema / properties / track / properties / value / items / properties / segment / properties / kind / description
        Added value: +"Class of the segment leaving the key; only Spline reads the tangents."
      • addedInput schema / properties / track / properties / value / items / properties / t_us / description
        Added value: +"Key time, timeline-absolute, µs."
      • changedInput schema / properties / track / properties / value / items / properties / value / description
        Previous value: -"Typed by `param_key`: a number for every scalar param (x, y, path_progress, scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity, gain_db, pan, effect params); an {r,g,b,a} colour (integers 0..255) for \"color\" — the Text and Color layers' colour. Path mode rejects independent x/y writes; use path_progress (a fraction, not a percentage); XY mode has no path_progress. A mismatch is refused naming the type the param takes."New value: +"Typed by `param_key`: a number for scalar params (x, y, path_progress, scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity, gain_db, pan, effect params), {r,g,b,a} (0..255) for \"color\". Path mode takes path_progress (a fraction) instead of x/y."
      • removedInput schema / properties / track / properties / value / items / properties / value / oneOf
        Removed value: -[
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "properties": {
        -      "a": {
        -        "type": "integer"
        -      },
        -      "b": {
        -        "type": "integer"
        -      },
        -      "g": {
        -        "type": "integer"
        -      },
        -      "r": {
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "r",
        -      "g",
        -      "b",
        -      "a"
        -    ],
        -    "type": "object"
        -  }
        -]
    • Changedset_position4 fields changed
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • changedInput schema / properties / position / description
        Previous value: -"{mode:XY,x,y} or {mode:Path,path:{nodes:[{id,point:{x,y},inHandle:{x,y},outHandle:{x,y},segment:Line|Cubic,tangentMode:Corner|Smooth|Auto}]},progress:Animated<number>}; Auto spatial handles are resolved from neighboring nodes; Smooth aligns handles; Corner leaves them independent. Progress 0..1 means distance along path; only Hold/Loop/PingPong extrapolation."New value: +"XY: `x`/`y` tracks in composition px. Path: `path.nodes` plus a `progress` track, 0..1 = distance along the path (Hold/Loop/PingPong extrapolation only)."
      • addedInput schema / properties / position / properties
        Added value: +{
        +  "mode": {
        +    "description": "XY: two scalar tracks. Path: a route plus a progress track.",
        +    "enum": [
        +      "XY",
        +      "Path"
        +    ],
        +    "type": "string"
        +  },
        +  "path": {
        +    "description": "Path mode: the route.",
        +    "properties": {
        +      "nodes": {
        +        "description": "1..128 nodes in route order.",
        +        "items": {
        +          "description": "One node of the route.",
        +          "properties": {
        +            "id": {
        +              "description": "Node id, unique and non-empty (yours to mint).",
        +              "type": "string"
        +            },
        +            "in_handle": {
        +              "description": "Arriving Bezier handle as a vector RELATIVE to `point`, composition px; {0,0} on a Line node.",
        +              "properties": {
        +                "x": {
        +                  "description": "x, composition px.",
        +                  "type": "number"
        +                },
        +                "y": {
        +                  "description": "y, composition px.",
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "x",
        +                "y"
        +              ],
        +              "type": "object"
        +            },
        +            "out_handle": {
        +              "description": "Leaving Bezier handle as a vector RELATIVE to `point`, composition px; {0,0} on a Line node.",
        +              "properties": {
        +                "x": {
        +                  "description": "x, composition px.",
        +                  "type": "number"
        +                },
        +                "y": {
        +                  "description": "y, composition px.",
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "x",
        +                "y"
        +              ],
        +              "type": "object"
        +            },
        +            "point": {
        +              "description": "Anchor point, composition px.",
        +              "properties": {
        +                "x": {
        +                  "description": "x, composition px.",
        +                  "type": "number"
        +                },
        +                "y": {
        +                  "description": "y, composition px.",
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "x",
        +                "y"
        +              ],
        +              "type": "object"
        +            },
        +            "segment": {
        +              "description": "Span LEAVING this node: Line, or Cubic (reads the handles).",
        +              "enum": [
        +                "Line",
        +                "Cubic"
        +              ],
        +              "type": "string"
        +            },
        +            "tangent_mode": {
        +              "description": "Corner: handles independent. Smooth: aligned directions, own lengths. Auto: solved from the neighbours on write.",
        +              "enum": [
        +                "Corner",
        +                "Smooth",
        +                "Auto"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "id",
        +            "point",
        +            "in_handle",
        +            "out_handle",
        +            "segment",
        +            "tangent_mode"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "nodes"
        +    ],
        +    "type": "object"
        +  },
        +  "progress": {
        +    "description": "Path mode: distance along the route, 0..1 (Hold / Loop / PingPong extrapolation only).",
        +    "properties": {
        +      "extrapolate": {
        +        "description": "What the track does outside its keys, per side: Hold | Loop | PingPong | Offset | Continue (see set_extrapolation).",
        +        "properties": {
        +          "after": {
        +            "description": "After the last key.",
        +            "enum": [
        +              "Hold",
        +              "Loop",
        +              "PingPong",
        +              "Offset",
        +              "Continue"
        +            ],
        +            "type": "string"
        +          },
        +          "before": {
        +            "description": "Before the first key.",
        +            "enum": [
        +              "Hold",
        +              "Loop",
        +              "PingPong",
        +              "Offset",
        +              "Continue"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "before",
        +          "after"
        +        ],
        +        "type": "object"
        +      },
        +      "mode": {
        +        "description": "Static holds one number; Keyframed animates the key array.",
        +        "enum": [
        +          "Static",
        +          "Keyframed"
        +        ],
        +        "type": "string"
        +      },
        +      "value": {
        +        "description": "Static: the number. Keyframed: the keys, in `set_param_track`'s key shape with layer-local `t_us`.",
        +        "type": [
        +          "number",
        +          "array"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "mode",
        +      "value"
        +    ],
        +    "type": "object"
        +  },
        +  "x": {
        +    "description": "XY mode: the x track, composition px.",
        +    "properties": {
        +      "extrapolate": {
        +        "description": "What the track does outside its keys, per side: Hold | Loop | PingPong | Offset | Continue (see set_extrapolation).",
        +        "properties": {
        +          "after": {
        +            "description": "After the last key.",
        +            "enum": [
        +              "Hold",
        +              "Loop",
        +              "PingPong",
        +              "Offset",
        +              "Continue"
        +            ],
        +            "type": "string"
        +          },
        +          "before": {
        +            "description": "Before the first key.",
        +            "enum": [
        +              "Hold",
        +              "Loop",
        +              "PingPong",
        +              "Offset",
        +              "Continue"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "before",
        +          "after"
        +        ],
        +        "type": "object"
        +      },
        +      "mode": {
        +        "description": "Static holds one number; Keyframed animates the key array.",
        +        "enum": [
        +          "Static",
        +          "Keyframed"
        +        ],
        +        "type": "string"
        +      },
        +      "value": {
        +        "description": "Static: the number. Keyframed: the keys, in `set_param_track`'s key shape with layer-local `t_us`.",
        +        "type": [
        +          "number",
        +          "array"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "mode",
        +      "value"
        +    ],
        +    "type": "object"
        +  },
        +  "y": {
        +    "description": "XY mode: the y track, composition px.",
        +    "properties": {
        +      "extrapolate": {
        +        "description": "What the track does outside its keys, per side: Hold | Loop | PingPong | Offset | Continue (see set_extrapolation).",
        +        "properties": {
        +          "after": {
        +            "description": "After the last key.",
        +            "enum": [
        +              "Hold",
        +              "Loop",
        +              "PingPong",
        +              "Offset",
        +              "Continue"
        +            ],
        +            "type": "string"
        +          },
        +          "before": {
        +            "description": "Before the first key.",
        +            "enum": [
        +              "Hold",
        +              "Loop",
        +              "PingPong",
        +              "Offset",
        +              "Continue"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "before",
        +          "after"
        +        ],
        +        "type": "object"
        +      },
        +      "mode": {
        +        "description": "Static holds one number; Keyframed animates the key array.",
        +        "enum": [
        +          "Static",
        +          "Keyframed"
        +        ],
        +        "type": "string"
        +      },
        +      "value": {
        +        "description": "Static: the number. Keyframed: the keys, in `set_param_track`'s key shape with layer-local `t_us`.",
        +        "type": [
        +          "number",
        +          "array"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "mode",
        +      "value"
        +    ],
        +    "type": "object"
        +  }
        +}
      • addedInput schema / properties / position / required
        Added value: +[
        +  "mode"
        +]
    • Addedset_project_settings
    • Changedset_role_flags5 fields changed
      • addedInput schema / properties / muted / description
        Added value: +"Silence the bus. Omitted leaves it alone."
      • changedInput schema / properties / muted / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
      • addedInput schema / properties / role / description
        Added value: +"The mixing bus."
      • addedInput schema / properties / solo / description
        Added value: +"Play this bus alone. Omitted leaves it alone."
      • changedInput schema / properties / solo / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
    • Changedset_role_gain2 fields changed
      • addedInput schema / properties / gain_db / description
        Added value: +"Bus gain, dB; 0 = unity."
      • addedInput schema / properties / role / description
        Added value: +"The mixing bus."
    • Changedset_scale_linked2 fields changed
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / linked / description
        Added value: +"true links scale_y to scale_x; false clears the flag only."
    • Addedset_track_flags
    • Addedshift_layers
    • Changedsmooth_keyframes5 fields changed
      • addedInput schema / properties / keyframe_id / description
        Added value: +"One key to smooth; omit for every key of the track."
      • changedInput schema / properties / keyframe_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / param_key / anyOf
        Added value: +[
        +  {
        +    "enum": [
        +      "x",
        +      "y",
        +      "path_progress",
        +      "scale_x",
        +      "scale_y",
        +      "rotation_deg",
        +      "anchor_x",
        +      "anchor_y",
        +      "opacity",
        +      "color",
        +      "gain_db",
        +      "pan"
        +    ]
        +  },
        +  {
        +    "pattern": "^effects\\[[0-9a-fA-F-]{36}\\]\\.params\\[[A-Za-z0-9_]+\\]$"
        +  }
        +]
      • addedInput schema / properties / param_key / description
        Added value: +"Animatable param: visual kinds x, y (path_progress in Path mode), scale_x, scale_y, rotation_deg, anchor_x, anchor_y, opacity; Text and Color color; Audio gain_db, pan; or an effect param as effects[<effect_id>].params[<key>]."
    • Changedsplit_layer4 fields changed
      • addedInput schema / properties / at_t_us / description
        Added value: +"Cut point, timeline; strictly inside the layer, µs."
      • addedInput schema / properties / escape_link / description
        Added value: +"Act on this layer alone, leaving its link partners in place. Default false."
      • changedInput schema / properties / escape_link / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
    • Changedsynthesize_speech10 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / properties / speed / default
        Removed value: -null
      • removedInput schema / properties / speed / format
        Removed value: -"float"
      • changedInput schema / properties / speed / type
        Previous value: -[
        -  "number",
        -  "null"
        -]New value: +"number"
      • removedInput schema / properties / t_start_us / default
        Removed value: -null
      • removedInput schema / properties / t_start_us / format
        Removed value: -"int64"
      • changedInput schema / properties / t_start_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / properties / target_track_id / default
        Removed value: -null
      • changedInput schema / properties / target_track_id / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • removedInput schema / title
        Removed value: -"SynthesizeSpeechArgs"
    • Changedtranscribe_clip16 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedInput schema / properties / backend / default
        Removed value: -null
      • changedInput schema / properties / backend / description
        Previous value: -"Optional STRICT backend override: `\"openai\"` | `\"whisper_cpp\"` |\n`\"funasr\"`. When set, that engine serves the request or the call errors\nnaming its exact gap (missing key / binary / model) — it never\nsubstitutes another engine, so an explicit local choice can never leak\naudio to a cloud provider. When omitted, the resolver walks the user's\npreference then availability. An unknown value is rejected."New value: +"Strict engine override: `\"openai\"` | `\"whisper_cpp\"` | `\"funasr\"`.\nThat engine serves or the call errors; nothing is substituted. Omitted:\nthe user's preferred engine, then availability."
      • changedInput schema / properties / backend / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • removedInput schema / properties / language / default
        Removed value: -null
      • changedInput schema / properties / language / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • removedInput schema / properties / t_end_us / default
        Removed value: -null
      • removedInput schema / properties / t_end_us / format
        Removed value: -"int64"
      • changedInput schema / properties / t_end_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / properties / t_start_us / default
        Removed value: -null
      • removedInput schema / properties / t_start_us / format
        Removed value: -"int64"
      • changedInput schema / properties / t_start_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • removedInput schema / properties / word_timestamps / default
        Removed value: -null
      • changedInput schema / properties / word_timestamps / description
        Previous value: -"Request exact per-word timestamps when the chosen backend can emit them\n(whisper.cpp → `-ojf`). Defaults to `true` — the backend's best\nprecision, at no extra engine cost; pass `false` to force the SRT-style\n(interpolated) output instead. OpenAI Whisper is SRT-only and ignores\nit either way; check `word_timing` in the result for what you got."New value: +"Ask for exact per-word times where the engine can emit them. Default\ntrue; `false` forces SRT-style interpolated words. The result's\n`word_timing` reports what you got."
      • changedInput schema / properties / word_timestamps / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
      • removedInput schema / title
        Removed value: -"TranscribeClipArgs"
    • Changedtranslate_path3 fields changed
      • addedInput schema / properties / dx / description
        Added value: +"Shift in x, composition px."
      • addedInput schema / properties / dy / description
        Added value: +"Shift in y, composition px."
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
    • Changedtrim_layer6 fields changed
      • addedInput schema / properties / edge / description
        Added value: +"Which edge moves: in = t_start_us, out = t_end_us."
      • addedInput schema / properties / edge / enum
        Added value: +[
        +  "in",
        +  "out"
        +]
      • addedInput schema / properties / escape_link / description
        Added value: +"Act on this layer alone, leaving its link partners in place. Default false."
      • changedInput schema / properties / escape_link / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / new_t_us / description
        Added value: +"Where the edge lands, timeline, µs."
    • Addedungroup_layer
    • Removedunlock_history
    • Addedupdate_composition
    • Changedupdate_effect7 fields changed
      • addedInput schema / properties / effect_id / description
        Added value: +"Effect id."
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / patch / properties / enabled / description
        Added value: +"false bypasses the effect, true applies it."
      • changedInput schema / properties / patch / properties / enabled / type
        Previous value: -[
        -  "boolean",
        -  "null"
        -]New value: +"boolean"
      • removedInput schema / properties / patch / properties / params / additionalProperties / anyOf
        Removed value: -[
        -  {
        -    "description": "An animation track: {\"mode\":\"Static\",\"value\":v} or {\"mode\":\"Keyframed\",\"value\":[{id, t_us, value, in, out, continuity, segment}, ...],\"extrapolate\":{before, after}}. Values are numbers. A segment's easing is the LEFT key's segment + out and the RIGHT key's in; each side's x is within [0, 1]. `extrapolate` defaults to Hold/Hold when omitted.",
        -    "properties": {
        -      "extrapolate": {
        -        "description": "What the track does outside its key range, per side (before the first key / after the last). The period is last.t − first.t; a single-key track never extrapolates.",
        -        "properties": {
        -          "after": {
        -            "description": "Hold = the end value (the clamp); Loop = repeat the cycle from the first key (a visible jump when first ≠ last — nothing bridges it); PingPong = odd cycles run backwards; Offset = each cycle adds the last-minus-first delta; Continue = carry the last segment's end velocity on as a line (zero after a Hold or procedural segment).",
        -            "enum": [
        -              "Hold",
        -              "Loop",
        -              "PingPong",
        -              "Offset",
        -              "Continue"
        -            ],
        -            "type": "string"
        -          },
        -          "before": {
        -            "description": "Hold = the end value (the clamp); Loop = repeat the cycle from the first key (a visible jump when first ≠ last — nothing bridges it); PingPong = odd cycles run backwards; Offset = each cycle adds the last-minus-first delta; Continue = carry the last segment's end velocity on as a line (zero after a Hold or procedural segment).",
        -            "enum": [
        -              "Hold",
        -              "Loop",
        -              "PingPong",
        -              "Offset",
        -              "Continue"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "before",
        -          "after"
        -        ],
        -        "type": "object"
        -      },
        -      "mode": {
        -        "enum": [
        -          "Static",
        -          "Keyframed"
        -        ],
        -        "type": "string"
        -      },
        -      "value": {
        -        "description": "Static: the held value (numbers). Keyframed: the keyframe array.",
        -        "items": {
        -          "properties": {
        -            "continuity": {
        -              "description": "With both sides Free: Smooth keeps their slopes locked equal on write, Broken lets them differ.",
        -              "enum": [
        -                "Smooth",
        -                "Broken"
        -              ],
        -              "type": "string"
        -            },
        -            "id": {
        -              "type": "string"
        -            },
        -            "in": {
        -              "description": "One side of a key: a control point in the owning segment's unit square (x = fraction of the segment's time span, y = fraction of its value span). `in` is the arriving cubic's second control point as stored (un-mirrored). mode \"Auto\" = re-solved on every write (monotone, no overshoot), \"Free\" = authored.",
        -              "properties": {
        -                "mode": {
        -                  "enum": [
        -                    "Auto",
        -                    "Free"
        -                  ],
        -                  "type": "string"
        -                },
        -                "x": {
        -                  "type": "number"
        -                },
        -                "y": {
        -                  "type": "number"
        -                }
        -              },
        -              "required": [
        -                "x",
        -                "y",
        -                "mode"
        -              ],
        -              "type": "object"
        -            },
        -            "out": {
        -              "description": "One side of a key: a control point in the owning segment's unit square (x = fraction of the segment's time span, y = fraction of its value span). `in` is the arriving cubic's second control point as stored (un-mirrored). mode \"Auto\" = re-solved on every write (monotone, no overshoot), \"Free\" = authored.",
        -              "properties": {
        -                "mode": {
        -                  "enum": [
        -                    "Auto",
        -                    "Free"
        -                  ],
        -                  "type": "string"
        -                },
        -                "x": {
        -                  "type": "number"
        -                },
        -                "y": {
        -                  "type": "number"
        -                }
        -              },
        -              "required": [
        -                "x",
        -                "y",
        -                "mode"
        -              ],
        -              "type": "object"
        -            },
        -            "segment": {
        -              "description": "Class of the segment LEAVING a key: {\"kind\":\"Spline\"} (its cubic is this key's out and the next key's in) | {\"kind\":\"Hold\"} | {\"kind\":\"Linear\"} | {\"kind\":\"Elastic\",\"dir\",amplitude?,period?} | {\"kind\":\"Bounce\",\"dir\"}.",
        -              "properties": {
        -                "amplitude": {
        -                  "description": "Elastic only: overshoot amplitude, >= 1. Omit for the default 1.",
        -                  "type": "number"
        -                },
        -                "dir": {
        -                  "description": "Elastic/Bounce only: easing direction.",
        -                  "enum": [
        -                    "In",
        -                    "Out",
        -                    "InOut"
        -                  ],
        -                  "type": "string"
        -                },
        -                "kind": {
        -                  "enum": [
        -                    "Spline",
        -                    "Hold",
        -                    "Linear",
        -                    "Elastic",
        -                    "Bounce"
        -                  ],
        -                  "type": "string"
        -                },
        -                "period": {
        -                  "description": "Elastic only: oscillation period, > 0. Omit for the default 0.3.",
        -                  "type": "number"
        -                }
        -              },
        -              "required": [
        -                "kind"
        -              ],
        -              "type": "object"
        -            },
        -            "t_us": {
        -              "type": "integer"
        -            },
        -            "value": {
        -              "type": "number"
        -            }
        -          },
        -          "required": [
        -            "id",
        -            "t_us",
        -            "value",
        -            "in",
        -            "out",
        -            "continuity",
        -            "segment"
        -          ],
        -          "type": "object"
        -        },
        -        "type": [
        -          "number",
        -          "array"
        -        ]
        -      }
        -    },
        -    "required": [
        -      "mode",
        -      "value"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / patch / properties / params / additionalProperties / description
        Added value: +"An AnimTrack — {\"mode\":\"Static\",\"value\":<number>} for a v1 param — or null to unset the key. Keyframe a visual effect param through set_keyframe instead."
      • addedInput schema / properties / patch / properties / params / additionalProperties / type
        Added value: +[
        +  "object",
        +  "null"
        +]
    • Addedupdate_keyframe
    • Changedupdate_layer7 fields changed
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • addedInput schema / properties / patch / description
        Added value: +"Envelope patch; only the fields you set apply."
      • removedInput schema / properties / patch / properties / enabled
        Removed value: -{
        -  "type": "boolean"
        -}
      • addedInput schema / properties / patch / properties / label / description
        Added value: +"Display name; null clears it."
      • addedInput schema / properties / patch / properties / locked / description
        Added value: +"Refuse edits to this layer."
      • addedInput schema / properties / patch / properties / t_end_us / description
        Added value: +"New timeline end (exclusive), µs (snapped and echoed)."
      • addedInput schema / properties / patch / properties / t_start_us / description
        Added value: +"New timeline start, µs (snapped to the grid and echoed)."
    • Changedupdate_layer_params36 fields changed
      • addedInput schema / properties / layer_id / description
        Added value: +"Layer id."
      • changedInput schema / properties / patch / description
        Previous value: -"Kind-tagged params patch. Must include `kind` matching the layer's kind ('Text' | 'VideoClip' | 'ImageOverlay' | 'Color' | 'Audio'). Only fields you include are applied."New value: +"Kind-tagged patch: `kind` must match the layer's, and only that kind's fields are accepted (one variant per kind); a key outside the set is refused naming it."
      • addedInput schema / properties / patch / oneOf
        Added value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "align": {
        +        "description": "Horizontal alignment inside the box.",
        +        "enum": [
        +          "Left",
        +          "Center",
        +          "Right"
        +        ],
        +        "type": "string"
        +      },
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "box_h": {
        +        "description": "Layout box height, composition px, local (before `scale`). null = auto height. Refused when the layer has no box_w and the patch supplies none.",
        +        "exclusiveMinimum": 0,
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "box_w": {
        +        "description": "Layout box width, composition px, local (before `scale`). null = auto width.",
        +        "exclusiveMinimum": 0,
        +        "type": [
        +          "number",
        +          "null"
        +        ]
        +      },
        +      "color": {
        +        "description": "Fill colour.",
        +        "properties": {
        +          "a": {
        +            "description": "Alpha 0..255; 255 opaque.",
        +            "type": "integer"
        +          },
        +          "b": {
        +            "description": "Blue 0..255.",
        +            "type": "integer"
        +          },
        +          "g": {
        +            "description": "Green 0..255.",
        +            "type": "integer"
        +          },
        +          "r": {
        +            "description": "Red 0..255.",
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "r",
        +          "g",
        +          "b",
        +          "a"
        +        ],
        +        "type": "object"
        +      },
        +      "content": {
        +        "description": "The text; newlines are honoured.",
        +        "type": "string"
        +      },
        +      "font_family": {
        +        "description": "Font family name.",
        +        "type": "string"
        +      },
        +      "font_size_px": {
        +        "description": "Font size, composition px.",
        +        "type": "number"
        +      },
        +      "font_weight": {
        +        "description": "CSS weight 100..900; 400 regular, 700 bold.",
        +        "type": "integer"
        +      },
        +      "italic": {
        +        "description": "Italic face.",
        +        "type": "boolean"
        +      },
        +      "kind": {
        +        "const": "Text",
        +        "description": "Fields of a Text layer."
        +      },
        +      "letter_spacing": {
        +        "description": "Letter spacing, px.",
        +        "type": "number"
        +      },
        +      "line_height": {
        +        "description": "Line height, px; 0 = the font metrics.",
        +        "type": "number"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "outline_color": {
        +        "description": "Stroke colour.",
        +        "properties": {
        +          "a": {
        +            "description": "Alpha 0..255; 255 opaque.",
        +            "type": "integer"
        +          },
        +          "b": {
        +            "description": "Blue 0..255.",
        +            "type": "integer"
        +          },
        +          "g": {
        +            "description": "Green 0..255.",
        +            "type": "integer"
        +          },
        +          "r": {
        +            "description": "Red 0..255.",
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "r",
        +          "g",
        +          "b",
        +          "a"
        +        ],
        +        "type": "object"
        +      },
        +      "outline_width": {
        +        "description": "Stroke width, composition px; 0 removes the outline.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "shadow": {
        +        "description": "Drop shadow, or null for none.",
        +        "properties": {
        +          "blur": {
        +            "description": "Blur radius, composition px; 0 is hard-edged.",
        +            "minimum": 0,
        +            "type": "number"
        +          },
        +          "color": {
        +            "description": "Shadow colour.",
        +            "properties": {
        +              "a": {
        +                "description": "Alpha 0..255; 255 opaque.",
        +                "type": "integer"
        +              },
        +              "b": {
        +                "description": "Blue 0..255.",
        +                "type": "integer"
        +              },
        +              "g": {
        +                "description": "Green 0..255.",
        +                "type": "integer"
        +              },
        +              "r": {
        +                "description": "Red 0..255.",
        +                "type": "integer"
        +              }
        +            },
        +            "required": [
        +              "r",
        +              "g",
        +              "b",
        +              "a"
        +            ],
        +            "type": "object"
        +          },
        +          "offset_x": {
        +            "description": "Horizontal offset, composition px.",
        +            "type": "number"
        +          },
        +          "offset_y": {
        +            "description": "Vertical offset, composition px.",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "color",
        +          "offset_x",
        +          "offset_y",
        +          "blur"
        +        ],
        +        "type": [
        +          "object",
        +          "null"
        +        ]
        +      },
        +      "valign": {
        +        "description": "Vertical alignment inside the box.",
        +        "enum": [
        +          "Top",
        +          "Middle",
        +          "Bottom"
        +        ],
        +        "type": "string"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "fade_in_us": {
        +        "description": "Fade-in length, µs.",
        +        "type": "integer"
        +      },
        +      "fade_out_us": {
        +        "description": "Fade-out length, µs.",
        +        "type": "integer"
        +      },
        +      "flip_h": {
        +        "description": "Mirror horizontally.",
        +        "type": "boolean"
        +      },
        +      "flip_v": {
        +        "description": "Mirror vertically.",
        +        "type": "boolean"
        +      },
        +      "kind": {
        +        "const": "VideoClip",
        +        "description": "Fields of a VideoClip layer."
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "speed": {
        +        "description": "Playback rate; 1 = normal.",
        +        "type": "number"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "src_out_us": {
        +        "description": "Source out point (exclusive), µs.",
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "fade_in_us": {
        +        "description": "Fade-in length, µs.",
        +        "type": "integer"
        +      },
        +      "fade_out_us": {
        +        "description": "Fade-out length, µs.",
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "const": "ImageOverlay",
        +        "description": "Fields of a ImageOverlay layer."
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "kind": {
        +        "const": "Motif",
        +        "description": "Fields of a Motif layer."
        +      },
        +      "motif_id": {
        +        "description": "Motif id from list_motifs.",
        +        "type": "string"
        +      },
        +      "motif_version": {
        +        "description": "Motif version to bind.",
        +        "type": "integer"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "props": {
        +        "description": "Motif props, matched against its props_schema.",
        +        "type": "object"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "color": {
        +        "description": "Fill colour.",
        +        "properties": {
        +          "a": {
        +            "description": "Alpha 0..255; 255 opaque.",
        +            "type": "integer"
        +          },
        +          "b": {
        +            "description": "Blue 0..255.",
        +            "type": "integer"
        +          },
        +          "g": {
        +            "description": "Green 0..255.",
        +            "type": "integer"
        +          },
        +          "r": {
        +            "description": "Red 0..255.",
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "r",
        +          "g",
        +          "b",
        +          "a"
        +        ],
        +        "type": "object"
        +      },
        +      "height": {
        +        "description": "Colour block height, px.",
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "const": "Color",
        +        "description": "Fields of a Color layer."
        +      },
        +      "width": {
        +        "description": "Colour block width, px.",
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "fade_in_us": {
        +        "description": "Fade-in length, µs.",
        +        "type": "integer"
        +      },
        +      "fade_out_us": {
        +        "description": "Fade-out length, µs.",
        +        "type": "integer"
        +      },
        +      "gain_db": {
        +        "description": "Gain, dB; written Static, replacing any keyframes.",
        +        "type": "number"
        +      },
        +      "kind": {
        +        "const": "Audio",
        +        "description": "Fields of a Audio layer."
        +      },
        +      "mute": {
        +        "description": "Silence the clip.",
        +        "type": "boolean"
        +      },
        +      "pan": {
        +        "description": "Stereo pan, -1 (left) .. 1 (right); written Static.",
        +        "type": "number"
        +      },
        +      "role": {
        +        "description": "Mixing bus.",
        +        "enum": [
        +          "dialogue",
        +          "music",
        +          "sfx",
        +          "voiceover"
        +        ],
        +        "type": "string"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "src_out_us": {
        +        "description": "Source out point (exclusive), µs.",
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "anchor_x": {
        +        "description": "Pivot x, fraction of the width (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "anchor_y": {
        +        "description": "Pivot y, fraction of the height (0.5 = centre).",
        +        "type": "number"
        +      },
        +      "blend_mode": {
        +        "description": "How the Group composites over what lies below.",
        +        "enum": [
        +          "Normal",
        +          "Multiply",
        +          "Screen",
        +          "Overlay",
        +          "Darken",
        +          "Lighten",
        +          "Add",
        +          "Difference"
        +        ],
        +        "type": "string"
        +      },
        +      "kind": {
        +        "const": "CompositionRef",
        +        "description": "Fields of a CompositionRef layer."
        +      },
        +      "opacity": {
        +        "description": "Opacity 0..1.",
        +        "type": "number"
        +      },
        +      "rotation_deg": {
        +        "description": "Rotation, degrees clockwise.",
        +        "type": "number"
        +      },
        +      "scale_x": {
        +        "description": "Horizontal scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "scale_y": {
        +        "description": "Vertical scale factor; 1 = native size.",
        +        "type": "number"
        +      },
        +      "src_in_us": {
        +        "description": "Source in point, µs.",
        +        "type": "integer"
        +      },
        +      "src_out_us": {
        +        "description": "Source out point (exclusive), µs.",
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "Anchor x, composition px (refused in Path mode: set_position / translate_path).",
        +        "type": "number"
        +      },
        +      "y": {
        +        "description": "Anchor y, composition px (refused in Path mode).",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "kind"
        +    ]
        +  }
        +]
      • removedInput schema / properties / patch / properties / align
        Removed value: -{
        -  "enum": [
        -    "Left",
        -    "Center",
        -    "Right"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / patch / properties / box_h
        Removed value: -{
        -  "description": "Layout box height in composition px, local (before `scale`). null = auto height. Refused when the layer has no box_w and the patch does not supply one.",
        -  "exclusiveMinimum": 0,
        -  "type": [
        -    "number",
        -    "null"
        -  ]
        -}
      • removedInput schema / properties / patch / properties / box_w
        Removed value: -{
        -  "description": "Layout box width in composition px, local (before `scale`). null = auto width.",
        -  "exclusiveMinimum": 0,
        -  "type": [
        -    "number",
        -    "null"
        -  ]
        -}
      • removedInput schema / properties / patch / properties / color
        Removed value: -{
        -  "properties": {
        -    "a": {
        -      "type": "integer"
        -    },
        -    "b": {
        -      "type": "integer"
        -    },
        -    "g": {
        -      "type": "integer"
        -    },
        -    "r": {
        -      "type": "integer"
        -    }
        -  },
        -  "required": [
        -    "r",
        -    "g",
        -    "b",
        -    "a"
        -  ],
        -  "type": "object"
        -}
      • removedInput schema / properties / patch / properties / content
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / patch / properties / fade_in_us
        Removed value: -{
        -  "type": "integer"
        -}
      • removedInput schema / properties / patch / properties / fade_out_us
        Removed value: -{
        -  "type": "integer"
        -}
      • removedInput schema / properties / patch / properties / flip_h
        Removed value: -{
        -  "type": "boolean"
        -}
      • removedInput schema / properties / patch / properties / flip_v
        Removed value: -{
        -  "type": "boolean"
        -}
      • removedInput schema / properties / patch / properties / font_family
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / patch / properties / font_size_px
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / gain_db
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / height
        Removed value: -{
        -  "type": "integer"
        -}
      • addedInput schema / properties / patch / properties / kind / description
        Added value: +"The layer's params.kind, as project://tracks reports it."
      • changedInput schema / properties / patch / properties / kind / enum
        Previous value: -[
        -  "Text",
        -  "VideoClip",
        -  "ImageOverlay",
        -  "Color",
        -  "Audio"
        -]New value: +[
        +  "Text",
        +  "VideoClip",
        +  "ImageOverlay",
        +  "Motif",
        +  "Color",
        +  "Audio",
        +  "CompositionRef"
        +]
      • removedInput schema / properties / patch / properties / letter_spacing
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / line_height
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / motif_id
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / patch / properties / motif_version
        Removed value: -{
        -  "type": "integer"
        -}
      • removedInput schema / properties / patch / properties / mute
        Removed value: -{
        -  "type": "boolean"
        -}
      • removedInput schema / properties / patch / properties / opacity
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / pan
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / props
        Removed value: -{
        -  "type": "object"
        -}
      • removedInput schema / properties / patch / properties / role
        Removed value: -{
        -  "enum": [
        -    "dialogue",
        -    "music",
        -    "sfx",
        -    "voiceover"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / patch / properties / scale_x
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / scale_y
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / speed
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / src_in_us
        Removed value: -{
        -  "type": "integer"
        -}
      • removedInput schema / properties / patch / properties / src_out_us
        Removed value: -{
        -  "type": "integer"
        -}
      • removedInput schema / properties / patch / properties / valign
        Removed value: -{
        -  "enum": [
        -    "Top",
        -    "Middle",
        -    "Bottom"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / patch / properties / width
        Removed value: -{
        -  "type": "integer"
        -}
      • removedInput schema / properties / patch / properties / x
        Removed value: -{
        -  "type": "number"
        -}
      • removedInput schema / properties / patch / properties / y
        Removed value: -{
        -  "type": "number"
        -}
    • Addedupdate_link
    • Changedupdate_marker11 fields changed
      • addedInput schema / properties / marker_id / description
        Added value: +"Marker id."
      • changedInput schema / properties / patch / description
        Previous value: -"Marker patch; only fields you set are applied. `end_t_us` can be set, never cleared (clear = remove + re-add). A marker's anchor is not patchable here — attach_marker and detach_marker set and clear it, and add_marker can create a marker already carrying one. Read `anchor_layer` on a marker to see whether it follows one."New value: +"Marker patch; only fields you set apply. `end_t_us` can be set, never cleared (remove + re-add). The anchor is `set_marker_anchor`'s, not patchable here."
      • addedInput schema / properties / patch / properties / color / description
        Added value: +"Marker colour."
      • addedInput schema / properties / patch / properties / color / properties / a / description
        Added value: +"Alpha 0..255; 255 opaque."
      • addedInput schema / properties / patch / properties / color / properties / b / description
        Added value: +"Blue 0..255."
      • addedInput schema / properties / patch / properties / color / properties / g / description
        Added value: +"Green 0..255."
      • addedInput schema / properties / patch / properties / color / properties / r / description
        Added value: +"Red 0..255."
      • addedInput schema / properties / patch / properties / end_t_us / description
        Added value: +"Region end, timeline; turns a point marker into a region, µs."
      • changedInput schema / properties / patch / properties / end_t_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
      • addedInput schema / properties / patch / properties / t_us / description
        Added value: +"New time, timeline, µs."
      • changedInput schema / properties / patch / properties / t_us / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +"integer"
    • Changedupdate_transition5 fields changed
      • addedInput schema / properties / direction / description
        Added value: +"Motion direction; rides with `kind` (Wipe / Slide need it, Crossfade refuses it)."
      • addedInput schema / properties / duration_us / description
        Added value: +"New transition length, µs."
      • changedInput schema / properties / extended_us / description
        Previous value: -"Explicit borrowed-tail target in µs, at most duration_us. Omit to keep trimmed ranges sacred: growth never borrows, shrink returns the borrow first. Negative = deliberate tail trim of the outgoing layer: all borrow returns, then its real content is trimmed by the remainder (the exit frame moves left; stored value becomes 0)."New value: +"Borrowed-tail target in µs, at most duration_us. Omit to preserve trimmed ranges; negative = deliberate tail trim of real content."
      • addedInput schema / properties / kind / description
        Added value: +"New kind; send `direction` with Wipe / Slide."
      • addedInput schema / properties / transition_id / description
        Added value: +"Transition id."
    • Changedwrite_motif_draft4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • changedInput schema / properties / from / type
        Previous value: -[
        -  "string",
        -  "null"
        -]New value: +"string"
      • changedInput schema / properties / manifest / description
        Previous value: -"The manifest as a JSON object (its `id`/`version` are ignored — app-assigned). Shape: `{ name, size:[w,h], default_duration_s, props_schema, ... }` — inspect a built-in via `get_motif_source` for an exact example. Rejected if malformed."New value: +"The manifest object (`id`/`version` are app-assigned and ignored): `{ name, size: [w, h], default_duration_s, props_schema, ... }` — copy a built-in's from `get_motif_source`."
      • removedInput schema / title
        Removed value: -"WriteMotifDraftArgs"
  5. 91 tool updatesv0.1.8
    • First observedadd_color_layer
    • First observedadd_effect
    • First observedadd_group_layer
    • First observedadd_marker
    • First observedadd_motif
    • First observedadd_track
    • First observedadd_transition
    • First observedadd_video_layer
    • First observedanalyze_clip
    • First observedapply_subtitles
    • First observedattach_marker
    • First observedauto_split_by_shot
    • First observedbegin_agent_session
    • First observedcheckpoint
    • First observedclear_keyframes
    • First observedcompare_frames
    • First observedcompositions_delete
    • First observeddelete_layer
    • First observeddelete_motif
    • First observeddescribe_clip
    • First observeddetach_marker
    • First observeddetect_pauses
    • First observeddry_run
    • First observedduplicate_layer
    • First observedend_agent_session
    • First observedextract_clip_audio
    • First observedfit_composition_to_layers
    • First observedget_motif_source
    • First observedget_param_track
    • First observedgroups_add_members
    • First observedgroups_create
    • First observedgroups_rename
    • First observedgroups_ungroup
    • First observedimport_media
    • First observedinstall_motif
    • First observedlaunch_weftcut
    • First observedlinks_add_members
    • First observedlinks_create
    • First observedlinks_dissolve
    • First observedlinks_remove_members
    • First observedlinks_rename
    • First observedlist_checkpoints
    • First observedlist_motifs
    • First observedlock_history
    • First observedmove_effect
    • First observedmove_layer
    • First observedmove_layers_to_composition
    • First observedmove_track
    • First observedpaste_layers
    • First observedping
    • First observedpreview_motif_draft
    • First observedredo
    • First observedremove_effect
    • First observedremove_keyframe
    • First observedremove_marker
    • First observedremove_media
    • First observedremove_pauses
    • First observedremove_track
    • First observedremove_transition
    • First observedrename_track
    • First observedrestack_layer
    • First observedrestore_checkpoint
    • First observedretime_keyframe
    • First observedripple_delete_gap
    • First observedripple_delete_layers
    • First observedset_composition
    • First observedset_extrapolation
    • First observedset_keyframe
    • First observedset_keyframe_easing
    • First observedset_keyframe_tangents
    • First observedset_layers_enabled
    • First observedset_param_track
    • First observedset_position
    • First observedset_role_flags
    • First observedset_role_gain
    • First observedset_scale_linked
    • First observedsmooth_keyframes
    • First observedsplit_layer
    • First observedsynthesize_speech
    • First observedtranscribe_clip
    • First observedtranslate_path
    • First observedtrim_layer
    • First observedundo
    • First observedunlock_history
    • First observedupdate_effect
    • First observedupdate_layer
    • First observedupdate_layer_params
    • First observedupdate_marker
    • First observedupdate_transition
    • First observedweftcut_status
    • First observedwrite_motif_draft

TDQS

A3.8/5.0

Scored across 103 tools

Disambiguation4/5

Despite the enormous surface, nearly every tool targets a distinct resource+action and the descriptions aggressively cross-reference siblings (e.g. set_layers_enabled vs update_layer, move_layer vs shift_layers vs move_layers_to_composition, delete_layers{ripple} vs ripple_delete_gap). A handful of families (time-shifting, splitting, keyframe editing) still require careful reading to pick the right member, so it is not quite 5.

Naming Consistency4/5

Overwhelmingly a consistent snake_case verb_noun pattern (add_layer, delete_track, set_keyframe, update_effect). Minor deviations exist in the read verbs — get_motif_source / get_param_track vs read_project vs list_motifs — and a few noun-first names like weftcut_status, but the convention is broadly predictable.

Tool Count2/5

103 tools is far beyond the typical 3-15 sweet spot and will strain an agent's selection even with strong descriptions. The domain (a full NLE with media, layers, keyframes, motifs, transcripts, history, sessions) justifies depth, but the count is heavy enough to be a real usability risk.

Completeness5/5

Coverage is exceptional: full lifecycle for layers, tracks, markers, links, transitions, effects, keyframes, compositions, motifs, media, captions, checkpoints, history, sessions and project settings, plus analysis, transcription, TTS and dry-run validation. No obvious dead ends for the stated video-editing purpose.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Web-based video editing platform that provides direct editing functionality through a Model Context Protocol server, supporting media file management, timeline editing, and advanced transformation effects.
    7
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server that enables LLM agents to control the OpenCut classic video editor's timeline through a Playwright-controlled browser, allowing automated video editing tasks like adding media, inserting clips, splitting, trimming, and exporting.
    7
    MIT