davinci-resolve-mcp 2.24.1 → 2.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,161 @@
2
2
 
3
3
  Release history for the DaVinci Resolve MCP Server. The latest release is summarized in the root README; older entries live here to keep the README focused.
4
4
 
5
+ ## What's New in v2.26.0
6
+
7
+ **Fusion group-settings helpers** — Three new `fusion_comp` actions for
8
+ authoring and patching `GroupOperator` macros without leaving the kernel.
9
+ `group_settings_export` writes a live group to a `.setting` file and returns a
10
+ parsed `published_inputs` summary using a balanced-brace walker so nested
11
+ `UserControls` / `ControlGroup` tables are bounded correctly (the original
12
+ flat-regex parser truncated `InstanceInput` bodies at the first inner `}`).
13
+ `group_settings_splice_inputs` replaces the `Inputs = ordered() { ... }` block
14
+ of one `.setting` with the matching block from another, preserving the source's
15
+ outer structure and inner `Tools`. `group_settings_load` applies a `.setting`
16
+ to a live group with an automatic timestamped backup, wrapped in
17
+ `StartUndo`/`Lock`/`LoadSettings`/`Unlock`/`EndUndo(True)` so Fusion's Ctrl+Z
18
+ reverses the change — verified live via direct BMD API.
19
+
20
+ **bulk_set_expressions** — Companion to the existing `bulk_set_inputs`. Batch
21
+ attach Fusion expressions across many timeline-item comps in one call. Each op
22
+ requires timeline scope plus `tool_name`, `input_name`, `expression`. Returns
23
+ per-op `success`/`error` rows + `op_count`, matching the bulk-inputs contract.
24
+ Useful for animating many controls at once (`time/30`, etc.) under a single
25
+ chat turn.
26
+
27
+ **Headless batch-runner CLI** — New
28
+ `davinci-resolve-mcp batch <plan|run|status|list|resume|cancel>` subcommand
29
+ drives `src/utils/media_analysis_jobs` from outside an MCP/chat client so long
30
+ analysis batches can run via cron, CI, or terminal without holding a chat turn
31
+ open. The orchestration loop and durable state stay in the existing jobs
32
+ engine; the CLI only handles argv, progress streaming, and exit codes
33
+ (`0` ok / `2` partial / `3` fatal / `130` Ctrl+C). JSON mode (`--json`)
34
+ emits one record per progress event for log scraping. Closes #42.
35
+
36
+ **Adapted from PR #40** — Group-settings work originated as a contribution
37
+ from @RaincloudTheDragon; PR #43 retains the keepable parts (parser, exporter,
38
+ splicer, loader, `bulk_set_expressions`) with a balanced-brace fix on the
39
+ parser and an undo+lock wrap on `group_settings_load`. The two AMZ-specific
40
+ templates and the static checklist from #40 were dropped as out-of-scope for a
41
+ general kernel.
42
+
43
+ ## What's New in v2.25.0
44
+
45
+ **Agentic flow improvements** — A second-pass review against the Claude
46
+ Certified Architect study material drove a sweep of correctness gains. Every
47
+ tool error now returns a structured envelope (`code` / `category` /
48
+ `retryable` / `reason` / `remediation` / `message`); `retryable` defaults are
49
+ locked per category so a host can make a one-shot retry decision without
50
+ inference. Compound-tool descriptions for `media_analysis` and
51
+ `timeline_item_color` adopt XML semantic tags (`<when_to_use>`, `<actions>`,
52
+ `<returns>`) for cheaper per-turn parsing. Repeated failures on the same
53
+ `(scope, action)` pair attach an `escalation` block on the 3rd response —
54
+ halts auto-retry loops with a `suggested_action` for the host. Batch
55
+ manifests now always carry `partial_success`, `completed_clip_ids`, and
56
+ `failed_clip_ids` for safe targeted retry.
57
+
58
+ **MCP resources surface** — 8 read-only resource URIs the host can poll
59
+ without paying a tool-turn cost: `status://mcp_version`,
60
+ `status://resolve_connection`, `status://current_project`,
61
+ `status://current_timeline`, `status://caps_preset`,
62
+ `analysis://recent_reports`, `capabilities://installed_tools`,
63
+ `capabilities://install_guidance`. Paired tools still work for hosts that
64
+ don't consume resources.
65
+
66
+ **MCP prompts surface** — 5 slash-command workflow templates:
67
+ `/davinci-resolve:analyze_and_propose_grade`,
68
+ `/davinci-resolve:match_bin_to_hero`,
69
+ `/davinci-resolve:verify_timeline_coverage`,
70
+ `/davinci-resolve:open_and_analyze_selection`,
71
+ `/davinci-resolve:prep_color_handoff`. First-class agentic intent, no
72
+ re-derivation from SKILL.md prose.
73
+
74
+ **Color-grading evidence base** — `timeline_item_color.grade_evidence_base`
75
+ composes `version_snapshot` + `node_graph` + `color_group` + coverage report
76
+ into a single `evidence_base` summary string; the SKILL guide now teaches
77
+ agents to lead any color recommendation with that line.
78
+ `timeline_item_color.propose_grade` formalizes a recommendation as a
79
+ validated structured plan (returns `plan_id` + `preview_path`; requires
80
+ explicit `execute=true` re-call). `bulk_match_to_hero` drives CDL-delta or
81
+ copy-grade across many targets with a `confirm_token` gate and dry-run
82
+ preview.
83
+
84
+ **Analysis caps layer** — Token-budget governance for analysis. 7 cap
85
+ dimensions across vision/transcription/job/clip/day scopes, 4 named presets
86
+ (`minimal` / `standard` / `generous` / `unlimited`), pre-call refusal with
87
+ `CAPS_REFUSAL` / `budget_exhausted` / `retryable: false`. New
88
+ `media_analysis` actions: `get_caps`, `set_caps_preset`. Token usage table
89
+ in the analysis DB plus a control-panel widget with gauges + override
90
+ inputs. Wall-clock timeout helper wraps vision/transcription call sites.
91
+
92
+ **Timeline versioning + analysis↔timeline marriage** — New
93
+ `timeline_versioning` MCP tool: every destructive timeline edit
94
+ auto-archives the current timeline into an Archive bin (compound, captions,
95
+ ripple, gap close, etc.), so versions can be diffed and rolled back. Run
96
+ scoping, schema v4 migrations, concurrency safety, structural snapshots,
97
+ action filtering, strict mode, auto-save preference, media-pool destructive
98
+ coverage, thumbnails. Backed by new modules `timeline_versioning.py`,
99
+ `timeline_brain_db.py`, `brain_edits.py`, `analysis_runs.py`,
100
+ `media_pool_changes.py`, `destructive_hook.py`. Surfaced in the control
101
+ panel's Review → History view.
102
+
103
+ **Async opt-in for long-running ops** — `analyze_clip` / `analyze_file` /
104
+ `commit_vision` accept `prefer_handle: true`. When set (and the estimated
105
+ runtime exceeds the configured threshold), the response is a fast handoff
106
+ with `job_id` + `status: "queued"`; poll `batch_job_status({job_id})`.
107
+ Default behavior unchanged.
108
+
109
+ **Aggregated provenance** — `summarize`,
110
+ `review_timeline_markers`, and `grade_evidence_base` now return a
111
+ `provenance` block: `source_reports[]` (clip_id, signature, report_path,
112
+ analyzed_at), `missing_reports[]` (per reason: `no_report` / `stale_report`
113
+ / `caps_refused`), and inline `[ref:<clip_id>]` citations in the human
114
+ summary text. Multi-clip claims are now traceable.
115
+
116
+ **Confirm-token gates on destructive batches** — `propose_grade`,
117
+ `bulk_match_to_hero`, and other multi-target writes now require an explicit
118
+ `confirm_token` on first execute (returned on the dry-run), with a
119
+ `pending_user_decision` error if missing.
120
+
121
+ **Action-help indirection** — `action_help(name=...)` returns the long-form
122
+ guidance for a single action, keeping the top-level tool descriptions
123
+ compact while preserving full per-action documentation.
124
+
125
+ **Tool-choice hint emission** — Analyze responses include a
126
+ `host_tool_choice_hint` block. Hosts that respect it pass
127
+ `tool_choice={type:"tool", name:"media_analysis"}` on the next API turn,
128
+ hard-locking the agent into the correct next call.
129
+
130
+ **Update process hardening** — Five improvements layered onto the
131
+ update-check path: active-job lock prevents updates mid-analysis, auto-stash
132
+ strategy preserves uncommitted work across updates, restart-needed marker
133
+ surfaces to the host, channels (`stable` / `beta` / `dev`), pre-update
134
+ breaking-change scan, integrity SHA verification of downloaded artifacts,
135
+ update history table, eager DB migration on update, and rollback to the
136
+ previous build. New `analysis_caps.py` + `update_check.py` revisions.
137
+
138
+ **Source-safe guardrails** — `destructive_hook.py` + decorator coverage
139
+ tests ensure every destructive surface goes through the auto-archive path
140
+ and never modifies, transcodes, or creates derivatives of source media.
141
+
142
+ **Test surface** — 30+ new test modules covering error envelopes,
143
+ failure tracking, partial-success manifests, `prefer_handle`, MCP resources,
144
+ MCP prompts, provenance, XML description shape, `action_help`,
145
+ `grade_evidence_base`, `propose_grade`, `bulk_match_to_hero`,
146
+ `confirm_token`, the analysis caps layer, caps integration / events /
147
+ history, timeline versioning, the timeline-brain DB, destructive decorator
148
+ coverage, the destructive hook, update hardening, and update history.
149
+
150
+ **Validation** — `tests/test_import.py`, `scripts/audit_api_parity.py`,
151
+ `node bin/davinci-resolve-mcp.mjs --version`, `npm pack --dry-run`, and
152
+ `git diff --check` all pass. 375 focused unit tests pass. Live Resolve
153
+ validation covered the D1–F2 surface end-to-end against project CKY /
154
+ Timeline 7 (D1 `retryable`, D2 XML descriptions, D3 partial-success on
155
+ plans + CAPS_REFUSAL manifests, E1 8 MCP resource URIs, E2 escalation on
156
+ 3× repeated failure, E3 `prefer_handle` job handoff with
157
+ `batch_job_status` polling, F1 provenance block) — 6/6 PASS on the
158
+ fourteenth-attempt smoke test. No source media was modified.
159
+
5
160
  ## What's New in v2.24.1
6
161
 
7
162
  **`npx davinci-resolve-mcp` no longer breaks MCP clients when invoked without a
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DaVinci Resolve MCP Server
2
2
 
3
- [![Version](https://img.shields.io/badge/version-2.24.1-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
3
+ [![Version](https://img.shields.io/badge/version-2.26.0-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
4
4
  [![npm](https://img.shields.io/npm/v/davinci-resolve-mcp.svg?label=npm&color=CB3837)](https://www.npmjs.com/package/davinci-resolve-mcp)
5
5
  [![API Coverage](https://img.shields.io/badge/API%20Coverage-100%25-brightgreen.svg)](docs/reference/api-coverage.md)
6
6
  [![Tools](https://img.shields.io/badge/MCP%20Tools-32%20(329%20full)-blue.svg)](#server-modes)
@@ -41,6 +41,7 @@ Usage:
41
41
  davinci-resolve-mcp doctor [install.py options]
42
42
  davinci-resolve-mcp server [server.py options]
43
43
  davinci-resolve-mcp control-panel [control panel options]
44
+ davinci-resolve-mcp batch <plan|run|status|list|resume|cancel> [options]
44
45
  davinci-resolve-mcp --version
45
46
  davinci-resolve-mcp --help
46
47
 
@@ -48,6 +49,8 @@ Examples:
48
49
  npx davinci-resolve-mcp setup
49
50
  npx davinci-resolve-mcp setup --clients cursor,claude-desktop
50
51
  npx davinci-resolve-mcp doctor
52
+ npx davinci-resolve-mcp batch run /path/to/footage --depth standard
53
+ npx davinci-resolve-mcp batch run /path/to/footage --json > progress.log
51
54
 
52
55
  Environment:
53
56
  DAVINCI_RESOLVE_MCP_INSTALL_ROOT Override the managed install directory.
@@ -335,6 +338,13 @@ function commandControlPanel(args) {
335
338
  run(command, commandArgs, { cwd: root });
336
339
  }
337
340
 
341
+ function commandBatch(args) {
342
+ const root = syncManagedInstall(installRoot());
343
+ const python = venvPython(root) || findSupportedPython();
344
+ const [command, ...commandArgs] = pythonCommandLine(python, ["-m", "src.batch_cli", ...args]);
345
+ run(command, commandArgs, { cwd: root });
346
+ }
347
+
338
348
  function main() {
339
349
  const argv = process.argv.slice(2);
340
350
  // No args → run the MCP stdio server. Anything printed to stdout would
@@ -366,6 +376,10 @@ function main() {
366
376
  commandControlPanel(args);
367
377
  return;
368
378
  }
379
+ if (command === "batch") {
380
+ commandBatch(args);
381
+ return;
382
+ }
369
383
 
370
384
  console.error(`Unknown command: ${command}\n`);
371
385
  console.error(usage());
package/docs/SKILL.md CHANGED
@@ -131,6 +131,11 @@ Code's Read tool handles JPG/PNG natively), produce the JSON, and call
131
131
  `pending_host_vision_analysis` — surface that explicitly; do not call the
132
132
  analysis complete.
133
133
 
134
+ The deferred payload also includes a `host_tool_choice_hint` block. Hosts that
135
+ respect this hint pass it as `tool_choice={type:"tool", name:"media_analysis"}`
136
+ on the next API turn, hard-locking the agent into the correct next call. Hosts
137
+ that don't recognize the field ignore it — the flow is unchanged for them.
138
+
134
139
  ## Local Control Panel
135
140
 
136
141
  If the user asks to open, launch, or inspect the Resolve MCP control panel, run
@@ -146,6 +151,11 @@ localhost URL. The panel is local and single-user; it is an operational surface
146
151
  for server status, Resolve clips, source-safe analysis jobs, preferences, and
147
152
  diagnostics as those sections are added.
148
153
 
154
+ The **Review tab → History** button opens the timeline-history surface:
155
+ per-timeline version chain, brain-edit deltas, manual archive, and rollback.
156
+ Backed by `timeline_versioning` MCP actions; see that tool's section below for
157
+ the underlying primitives.
158
+
149
159
  ---
150
160
 
151
161
  ## Editorial Memory And Decision-Making
@@ -159,8 +169,15 @@ screen geography, continuity, and coverage variety.
159
169
  Before analyzing or rebuilding anything, check whether the active project already
160
170
  contains useful evidence:
161
171
 
162
- - `media_analysis(action="summarize")`
163
- - `media_analysis(action="get_report")` when a manifest or report path is known
172
+ - `media_analysis(action="coverage_report", params={"target": {...}})` — the
173
+ pre-flight contract. Pure read; never triggers analysis. Returns per-clip
174
+ state (analyzed / stale / missing / reuse_blocked / superseded_by_relink),
175
+ layer presence, `source_trust` tier, and a `recommended_action`. The response
176
+ carries an `evidence_base` summary string — **lead any editorial or color
177
+ recommendation with that line, before the creative answer.**
178
+ - `media_analysis(action="summarize")` for project-wide rollup of warnings,
179
+ motion distribution, and signed-report counts.
180
+ - `media_analysis(action="get_report")` when a manifest or report path is known.
164
181
  - `timeline(action="list")`
165
182
  - `timeline(action="get_current")`
166
183
  - `timeline(action="probe_timeline_structure")`
@@ -168,15 +185,24 @@ contains useful evidence:
168
185
  - `timeline_markers(action="get_all")`
169
186
  - `media_analysis(action="review_timeline_markers")` when marker imagery matters
170
187
 
171
- Reuse prior analysis unless it is stale, incomplete, or missing the modality the
172
- user is asking for. For example, do not re-run visual analysis just because the
173
- edit task is new if a current report already has keyframes, motion variance, and
174
- usable visual descriptions. Add transcription, host_chat_paths vision (followed
175
- by commit_vision), marker review, or source range checks only when that missing
176
- evidence changes the decision. Use `force_refresh=true` only when the user asks for a fresh read or
188
+ Reuse prior analysis unless it is stale, incomplete, missing a modality, or
189
+ flagged `superseded_by_relink` because Resolve's source clip was replaced after
190
+ analysis ran. Coverage_report surfaces all of these in one read. Do not re-run
191
+ visual analysis just because the edit task is new if a current report already
192
+ has keyframes, motion variance, and usable visual descriptions. Add
193
+ transcription, host_chat_paths vision (followed by commit_vision), marker
194
+ review, or source range checks only when that missing evidence changes the
195
+ decision. Use `force_refresh=true` only when the user asks for a fresh read or
177
196
  when cache signatures show the source, prompt, depth, or requested modality has
178
197
  changed.
179
198
 
199
+ Source-trust filtering: `coverage_report` accepts `min_source_trust` (one of
200
+ `auto`, `filename`, `low`, `medium`, `high`). Clips below the threshold appear
201
+ in `summary.clips_needs_higher_trust` and are reported with
202
+ `below_min_source_trust=true`. Use `medium` for routine work, `high` for
203
+ shot-matching or look-development passes where confident scene/identity reads
204
+ matter.
205
+
180
206
  For finished-video editorial work, scene detection and motion variance are
181
207
  guardrails, not story. Use them to avoid black frames, flash frames, corrupt
182
208
  ranges, and accidental cut points. Let transcript, sound events, complete
@@ -217,6 +243,13 @@ Be explicit about the API boundary:
217
243
  wheel values, log/HDR palette values, curves, qualifiers, power windows,
218
244
  tracking, Color Warper, and detailed ResolveFX/OFX parameter edits.
219
245
 
246
+ Before any color recommendation, run
247
+ `media_analysis(action="coverage_report", params={"target": {...},
248
+ "min_source_trust": "medium"})` (use `"high"` for shot-matching or
249
+ look-development passes). Lead the response with the returned `evidence_base`
250
+ line before the grade plan. Coverage_report surfaces relink-superseded clips
251
+ that must be re-analyzed before being graded from prior visual descriptions.
252
+
220
253
  For safe color work, start with `timeline_item_color(action="grade_boundary_report")`,
221
254
  `timeline_item_color(action="grade_version_snapshot")`,
222
255
  `timeline_item_color(action="probe_node_graph")`, and a Resolve-rendered frame
@@ -415,12 +448,13 @@ report reuse, persisted analysis execution, host_chat_paths visual review
415
448
  metadata/marker writeback, and timeline-level editorial helpers.
416
449
 
417
450
  Key actions: `capabilities`, `install_guidance`, `resolve_output_root`, `plan`,
418
- `analyze_file`, `analyze_clip`, `analyze_bin`, `analyze_project`,
419
- `detect_sync_events`, `add_sync_event_markers`, `publish_clip_metadata`,
420
- `commit_vision`, `summarize`, `get_report`, `build_index`, `index_status`,
421
- `query_index`, `start_batch_job`, `run_batch_job_slice`, `batch_job_status`,
422
- `list_batch_jobs`, `cancel_batch_job`, `resume_batch_job`,
423
- `review_timeline_markers`, and `cleanup_artifacts`.
451
+ `coverage_report`, `analyze_file`, `analyze_clip`, `analyze_bin`,
452
+ `analyze_project`, `detect_sync_events`, `add_sync_event_markers`,
453
+ `publish_clip_metadata`, `commit_vision`, `summarize`, `get_report`,
454
+ `build_index`, `index_status`, `query_index`, `start_batch_job`,
455
+ `run_batch_job_slice`, `batch_job_status`, `list_batch_jobs`,
456
+ `cancel_batch_job`, `resume_batch_job`, `review_timeline_markers`, and
457
+ `cleanup_artifacts`.
424
458
  The tool never installs
425
459
  dependencies and validates that outputs stay under
426
460
  `davinci-resolve-mcp-analysis` project roots rather than beside source media.
@@ -434,14 +468,29 @@ for existing reports. `quick` uses ffprobe metadata; `standard` adds ffmpeg
434
468
  read-through checks,
435
469
  cut-boundary analysis from full-stream scene detection, flash-frame candidates,
436
470
  motion/variance scoring, analysis keyframes, and sidecar reports.
437
- By default, planning checks the active project's analysis root for existing
438
- reports and marks matching clips `skip_execution=true` when those reports already
439
- contain the requested technical, motion, transcription, and vision layers.
471
+ By default, planning checks the active project's analysis root and bounded
472
+ related project-version roots for existing reports, then marks matching clips
473
+ `skip_execution=true` when those reports already contain the requested
474
+ technical, motion, transcription, and vision layers.
475
+ Resolve clip records also carry the published third-party
476
+ `davinci_resolve_mcp.analysis_report_path` when metadata writeback has run; use
477
+ that provenance as a first-class reuse hint even if the report lives under a
478
+ previous project-version analysis root.
479
+ The planner also maintains an `analysis_registry.json` under the analysis base
480
+ root. This registry indexes report paths by source path, clip id, media id, and
481
+ signature so project renames and versioned Resolve projects can still find prior
482
+ work quickly.
440
483
  Reports include cache signatures with source stat, depth, frame budget, prompt
441
484
  hash, and requested modalities. Use `force_refresh=true` for a fresh read,
442
485
  `max_report_age_days` for freshness limits, and `reuse_policy="fresh"` when
443
486
  unsigned older reports should not be reused. Pass `reuse_existing=false` only
444
- when the user explicitly wants to ignore memory.
487
+ when the user explicitly wants to ignore memory; pass
488
+ `search_related_project_roots=false` only for intentionally isolated runs.
489
+ If Resolve metadata shows prior MCP analysis but the planner cannot validate a
490
+ matching report, execution returns `status="reuse_blocked"` instead of silently
491
+ reanalyzing. Treat that as a project-memory integrity warning; restore the
492
+ report or pass `force_refresh=true` only when the user explicitly wants fresh
493
+ analysis.
445
494
  Transcription, visual analysis, metadata writeback, and Media Pool marker
446
495
  writeback are default-on. Vision uses
447
496
  `vision.provider="host_chat_paths"`: analyze actions extract representative
@@ -466,6 +515,10 @@ plus before/after cut-boundary frames as the sampled set. Skipping
466
515
  `commit_vision` leaves the run in `pending_host_vision_analysis` — that is a
467
516
  failure mode to surface, not a silent downgrade. The local mock providers are
468
517
  for tests and do not send frames off-machine.
518
+
519
+ When creating timelines through `media_pool`, use `if_exists="reuse"` for
520
+ idempotent reruns, `if_exists="version"` for deliberate alternate cuts, and
521
+ `if_exists="fail"` when duplicate names indicate a workflow error.
469
522
  Use `detect_sync_events` before multicam setup, deliverable QC, or single-camera
470
523
  sync review when the user needs likely 2-pop or slate-clap locations. It reads
471
524
  source audio through FFmpeg/FFprobe only, returns advisory frames/timecodes and
@@ -497,6 +550,111 @@ only when that mutation is intentional.
497
550
 
498
551
  ### Timelines
499
552
 
553
+ **`timeline_versioning`** — Version-on-mutate, archive, rollback, brain-edit history (C6).
554
+
555
+ Every destructive timeline op (compound, captions, ripple delete, gap close,
556
+ retime, marker batch, track add/delete, take swaps, color grade, etc.) auto-
557
+ archives the working timeline to the `Archive` bin under an `analysis_run_id`
558
+ before the mutation runs. This tool surfaces and controls that history.
559
+
560
+ Key actions:
561
+ - `begin_run(label?, initiator?, analysis_run_id?)` — open a multi-step run.
562
+ Subsequent destructive calls auto-thread this run's ID, so a brain
563
+ operation that touches 5 clips creates ONE archive + 5 logged edits
564
+ instead of 5 separate archives.
565
+ - `end_run(analysis_run_id?)` — close the run; aggregates brain_edits into
566
+ per-metric rollup in `analysis_runs.summary_json`.
567
+ - `list_runs(limit?)` — recent runs newest first with their summaries.
568
+ - `archive_current(reason?, analysis_run_id?)` — manual checkpoint of the
569
+ current timeline. Idempotent within an `analysis_run_id`. Also captures a
570
+ structural snapshot (every clip's placement, written to `timeline_clip_usage`)
571
+ and a thumbnail (when the Color page has a current clip).
572
+ - `list_versions(timeline_name)` — version chain, oldest first. Each row
573
+ includes `archived_timeline_name`, `created_at`, `analysis_run_id`,
574
+ `initiator`, `thumbnail_path`, and `drt_export_path` (set when the version
575
+ was retention-collapsed to disk).
576
+ - `diff_versions(timeline_name, from_version, to_version)` — structural diff
577
+ between two snapshots: `{added, removed, moved}` lists of clips by
578
+ media_pool_item_id and timeline position.
579
+ - `get_history(timeline_name?, analysis_run_id?, limit?)` — brain-edit rows
580
+ with `edit_type`, `target_metric`, `before_value`, `after_value`, `delta`,
581
+ `rationale`, and `initiator`. Filter by timeline or run; defaults to 50.
582
+ - `media_pool_changes(analysis_run_id?, media_pool_action?, limit?)` —
583
+ destructive media-pool history (deletes, replaces, relinks) from the
584
+ `media_pool_changes` table. Separate from brain_edits because the
585
+ addressable entity is a media_pool_item, not a timeline.
586
+ - `rollback(timeline_name, version, analysis_run_id?)` — archive current first,
587
+ then duplicate the archived version back as a new `<name>_rolled_back_<HHMMSS>`.
588
+ - `prune(timeline_name, keep_n=10)` — collapse old versions to `.drt` exports
589
+ under `<project>/_soul/timeline_versions/<slug>/` and remove them from the
590
+ bin. DB row preserved with `drt_export_path` populated for later rollback.
591
+ - `registry()` — cross-project brain-edits registry that lives at the analysis
592
+ base root (one level above each project_root). Mirrors `analysis_registry.json`.
593
+
594
+ **Strict mode** — `timeline.delete_timelines`, `timeline.delete_track`, and
595
+ `timeline.delete_clips(ripple=True)` REFUSE to run when the pre-mutation
596
+ archive can't be created. Pass `strict=true` on any destructive op to opt in.
597
+ This prevents catastrophic ops from proceeding when versioning is broken.
598
+
599
+ **Action filtering** — `timeline_item.set_property(key='Notes')` and
600
+ `timeline.set_clip_property(key='Notes'|'Comments')` bypass versioning because
601
+ free-text metadata isn't worth archiving. See `NO_ARCHIVE_ON_KEYS` in
602
+ `src/utils/destructive_hook.py` to add more.
603
+
604
+ **Preferences** — `timeline_versioning_auto_save_after_archive` (default false)
605
+ triggers `project.SaveProject()` after every archive so Resolve crashes don't
606
+ lose history. Configure via the `setup` tool's preferences.
607
+
608
+ ### Analysis Caps
609
+
610
+ `media_analysis` honors a project-wide caps preset that controls 7 dimensions
611
+ of analysis cost: response payload size, frames per clip, vision tokens per
612
+ clip / per job / per day, wall-clock seconds per call, and the maximum frame
613
+ image dimension before upload. Four named presets, plus per-field overrides.
614
+
615
+ | Dimension | minimal | standard | generous | unlimited |
616
+ |------------------------------:|--------:|---------:|----------:|----------:|
617
+ | response_chars | 5,000 | 25,000 | 100,000 | none |
618
+ | vision_tokens_per_clip | 5,000 | 25,000 | 100,000 | none |
619
+ | frames_per_clip | 4 | 8 | 24 | none |
620
+ | vision_tokens_per_job | 50,000 | 250,000 | 1,000,000 | none |
621
+ | vision_tokens_per_day | 100,000 | 500,000 | 2,000,000 | none |
622
+ | wall_clock_seconds_per_call | 30 | 90 | 300 | none |
623
+ | max_frame_dim_pixels | 512 | 768 | 1280 | none |
624
+
625
+ Default preset: `standard`. Set via `media_analysis(action="set_caps_preset",
626
+ preset=…, overrides={...})` or the dashboard's **Preferences → Analysis Caps**
627
+ panel. Inspect via `media_analysis(action="get_caps")` which returns the
628
+ effective values + a usage rollup (clip / job / day) with percent-consumed.
629
+ `media_analysis(action="get_usage", scope="day"|"job"|"clip")` returns raw
630
+ counts for one scope. Usage is tracked in
631
+ `<project>/_soul/timeline_brain.sqlite` (`analysis_token_usage` table).
632
+
633
+ The caps layer:
634
+ - Slices `frame_paths` to `frames_per_clip` before the host LLM sees them.
635
+ - Downscales each sampled frame in place to `max_frame_dim_pixels` (Pillow;
636
+ degrades silently to original-resolution upload if not installed).
637
+ - Trims the analysis response payload to `response_chars`, dropping the
638
+ largest list/string fields first and marking the trim under `_trimmed`.
639
+ - Records actual token usage from the host's `commit_vision` payload's
640
+ optional `usage: {vision_tokens, ...}` block. Hosts that don't report
641
+ tokens still get `frames_uploaded` recorded.
642
+
643
+ Wall-clock timeout + cumulative-budget refusal are implemented in
644
+ `src/utils/analysis_caps.py` and ready to hook at additional call sites in
645
+ the analysis pipeline; the initial integration is at frame sampling +
646
+ response construction + commit_vision usage recording.
647
+
648
+ **Declared edits** — when the brain (or an agent acting deliberately) wants to
649
+ measure an edit, pass `metric`, `direction`, and `rationale` in the params of
650
+ the destructive call. The hook captures `before_value` and `after_value` from
651
+ the live timeline (using the metric vocabulary in `brain_edits.py`) and writes
652
+ them to the `brain_edits` row. Without these, the edit is still logged but with
653
+ null metric — gives history without requiring deliberate intent.
654
+
655
+ Supported metrics: `duration_seconds`, `avg_performance_score`, `clip_count`,
656
+ `gap_count`, `total_gap_seconds`, `redundancy_score`.
657
+
500
658
  **`timeline`** — Timeline operations: tracks, clips, import/export, generators.
501
659
 
502
660
  Key actions:
@@ -765,6 +923,18 @@ Key actions:
765
923
  - `start_undo(name?)` / `end_undo(keep?)`
766
924
  - `bulk_set_inputs(ops)` — batch set inputs across multiple timeline item comps in
767
925
  one call; each op requires timeline scope plus `tool_name`, `input_name`, `value`
926
+ - `bulk_set_expressions(ops)` — batch attach expressions across multiple timeline
927
+ item comps in one call; each op requires timeline scope plus `tool_name`,
928
+ `input_name`, `expression`
929
+ - `group_settings_export(group_name, path, include_advisory?)` — write a
930
+ `GroupOperator` to disk and return a parsed published-input summary
931
+ - `group_settings_splice_inputs(source_path, template_path, dest_path?, source_group_name?, template_group_name?)` —
932
+ replace one `.setting` file's `Inputs = ordered() { ... }` block with the
933
+ matching block from another, preserving inner tools and outer structure;
934
+ balanced-brace parser handles nested `UserControls`
935
+ - `group_settings_load(group_name, settings_path, backup_path?, undo_name?)` —
936
+ apply a `.setting` to a live group with an auto backup and an undo wrap so
937
+ Ctrl+Z reverses the change
768
938
 
769
939
  Fusion Composition kernel actions (v2.12.0+) add safer graph inspection and
770
940
  mutation wrappers around the raw Fusion API:
@@ -345,6 +345,45 @@ Do not promise node labels or node colors unless the available API path can
345
345
  actually write them. Existing labels, LUTs, tools, and cache state can be
346
346
  inspected and reported.
347
347
 
348
+ ## Pre-flight Coverage Check (required)
349
+
350
+ Before answering any shot-matching, look-development, or per-clip grade question,
351
+ call `timeline_item_color(action="grade_evidence_base", params={...})` against the
352
+ target clip. The action is a pure read — it never mutates and never triggers
353
+ analysis. It composes the version snapshot, node graph, color group, and
354
+ `coverage_report` for the underlying media pool item into a single one-line
355
+ `evidence_base` string. **Lead your response with that line — before any grade
356
+ recommendation.**
357
+
358
+ For sequence-wide checks (multiple clips, bin, timeline), use
359
+ `media_analysis(action="coverage_report")` as before — the broader pre-flight
360
+ covers all targets in one call.
361
+
362
+ The response carries an `evidence_base` string and per-clip details: layer
363
+ presence, source-trust tier, staleness reasons, relink supersedure, and a
364
+ `recommended_action`. **Lead your response to the user with the `evidence_base`
365
+ line — before any grade recommendation.**
366
+
367
+ For color work, source-trust matters more than for editorial. Use the
368
+ `min_source_trust` parameter to gate recommendations:
369
+
370
+ - `coverage_report(min_source_trust="medium")` for routine corrections.
371
+ - `coverage_report(min_source_trust="high")` for hero shots, look-development
372
+ passes, and any decision that depends on confident scene/lighting recognition.
373
+
374
+ Clips below the threshold appear in `summary.clips_needs_higher_trust` and
375
+ should be re-analyzed with an explicit higher `source_trust` before being graded
376
+ from their visual descriptions.
377
+
378
+ Relink-superseded clips (`superseded_by_relink=true`) must never be reasoned
379
+ about as if the prior analysis still describes the current media. The prior
380
+ report is preserved for reference, but a re-analysis is required before
381
+ shot-matching or look development is grounded.
382
+
383
+ If existing analysis flags exposure issues, clipped highlights, color cast
384
+ warnings, or scene-of-interest notes, surface those before proposing CDL or
385
+ node-graph changes.
386
+
348
387
  ## Agent Response Rules
349
388
 
350
389
  When answering a color request, classify the requested operation:
@@ -368,6 +407,7 @@ DCTL, or CDL is equivalent to a full colorist pass.
368
407
 
369
408
  ## Useful MCP Calls
370
409
 
410
+ - `media_analysis(action="coverage_report", params={...})` — pre-flight evidence-base check
371
411
  - `resolve_control(action="open_page", params={"page": "color"})`
372
412
  - `timeline_item_color(action="grade_boundary_report", params={...})`
373
413
  - `timeline_item_color(action="probe_grade_item", params={...})`
@@ -38,6 +38,35 @@ the user explicitly needs. A new request for edit advice is not automatically a
38
38
  reason to re-run visual analysis if the prior report already has current
39
39
  technical data, motion/keyframe evidence, and useful visual descriptions.
40
40
 
41
+ ## Pre-flight Coverage Check (required)
42
+
43
+ Before answering any cut, pacing, story-structure, or shot-selection question,
44
+ call `media_analysis(action="coverage_report")` against the target you're about
45
+ to reason about (timeline, bin, selection, or project). The action is a pure
46
+ read — it never triggers analysis.
47
+
48
+ The response includes an `evidence_base` string (e.g. `"evidence base: 38/40
49
+ clips analyzed (95%), 1 stale, 1 reuse-blocked."`) and a per-clip breakdown
50
+ covering layer presence, source-trust tier, staleness reasons, relink
51
+ supersedure, and a `recommended_action`.
52
+
53
+ **The response to the user must lead with the `evidence_base` line — before any
54
+ creative recommendation.** This mirrors the `pending_host_vision_analysis`
55
+ honesty pattern: do not silently answer from incomplete evidence. If coverage
56
+ is below the threshold the user's question depends on, surface that gap first
57
+ and offer to fill it (e.g. "3 of the clips on this timeline have no transcript;
58
+ analyzing them first will materially change my cut-point suggestions — run it
59
+ now?").
60
+
61
+ When the gap is small and the user is okay proceeding, still answer — but mark
62
+ the answer as evidence-thin so they can re-ask once gaps are filled. Do NOT
63
+ auto-trigger analysis to fix gaps unless the user explicitly asks.
64
+
65
+ Relink-superseded clips (`superseded_by_relink=true`) must never be reasoned
66
+ about as if the prior analysis still describes them. The prior report is
67
+ preserved for reference, but a re-analysis is required before the recommendation
68
+ is grounded.
69
+
41
70
  ## Frame Choice
42
71
 
43
72
  Find the decisive frame, not just the technically clean frame. Useful cut points
@@ -30,10 +30,40 @@ All actions are exposed through `fusion_comp`.
30
30
  | `safe_set_inputs` | Batch write inputs on one tool with optional readback classification. |
31
31
  | `safe_connect_tools` | Validate source/target tools before connecting a source output to a target input. |
32
32
  | `fusion_boundary_report` | Return graph capabilities plus a composition snapshot for the selected comp scope. |
33
+ | `bulk_set_expressions` | Batch `SetExpression` across scoped timeline-item Fusion comps. Each op needs `tool_name`, `input_name`, `expression`, plus a timeline scope. Wraps each op in `StartUndo`/`EndUndo` + `comp.Lock`. |
34
+ | `group_settings_export` | Save a named `GroupOperator`'s settings to a `.setting` file via `SaveSettings`, returning a parsed published-input summary. |
35
+ | `group_settings_splice_inputs` | Replace the `Inputs = ordered() { ... }` block of `source_path` with the matching block from `template_path` and write `dest_path`. Read-only against Resolve; pure file operation. |
36
+ | `group_settings_load` | Backup the current group state, then `LoadSettings` from a `.setting` file. Wrapped in `StartUndo`/`EndUndo` + `comp.Lock` so Fusion's Ctrl+Z can reverse it. Backup path is returned alongside any error. |
37
+ | `probe_group_published_inputs` | Read live published `Input1..InputN` slots off a `GroupOperator`, optionally cross-referenced with a `.setting` file summary. |
33
38
 
34
39
  The pre-existing `bulk_set_inputs` action remains the batch path for applying
35
40
  input writes across multiple explicitly scoped timeline-item Fusion comps.
36
41
 
42
+ ### `group_settings_splice_inputs` notes
43
+
44
+ The Fusion `.setting` format is a Lua-like nested structure: an InstanceInput
45
+ commonly contains `UserControls = ordered() { Custom = { ... } }` tables, so any
46
+ parsing that uses a flat regex will truncate bodies at the first inner `}`. This
47
+ kernel uses balanced-brace scanning end-to-end. Practical implications:
48
+
49
+ - The action only swaps the published `Inputs = ordered() { ... }` block. The
50
+ group's outer name, inner `Tools = ordered() { ... }` section, and surrounding
51
+ structure are preserved byte-for-byte.
52
+ - You must provide the *new* layout as a real `.setting` file (typically
53
+ exported from a known-good group via `group_settings_export`). The kernel does
54
+ not ship hardcoded templates.
55
+ - `template_group_name` is optional when the template file contains a single
56
+ `GroupOperator`; pass it when the template file contains multiple groups and
57
+ you want a specific one.
58
+
59
+ ### `group_settings_load` Edit-page caveat
60
+
61
+ `LoadSettings` may update inner tool wiring but not refresh Edit-page
62
+ `InstanceInput` order until the group is selected in Fusion and reloaded via UI.
63
+ This is a Resolve quirk, not a kernel bug. The action always backs up the group
64
+ to a timestamped sibling of `settings_path` first; the backup path is returned
65
+ in success and in error responses.
66
+
37
67
  ## Scope Matrix
38
68
 
39
69
  | Scope | Probe Support | Mutation Support | Notes |
@@ -6,7 +6,7 @@ Complete Resolve scripting API coverage, live-test status, and method-by-method
6
6
 
7
7
  | Metric | Value |
8
8
  |--------|-------|
9
- | MCP Tools | **32** compound (default) / **329** granular |
9
+ | MCP Tools | **33** compound (default) / **329** granular |
10
10
  | Kernel Actions | **136** guarded MCP workflow actions across 9 compound tools |
11
11
  | API Methods Covered | **336/336** (100%) |
12
12
  | Methods Live Tested | **331/336** (98.5%) |
@@ -17,7 +17,13 @@ Complete Resolve scripting API coverage, live-test status, and method-by-method
17
17
 
18
18
  ## API Coverage
19
19
 
20
- Every non-deprecated method in the DaVinci Resolve Scripting API is covered. The default compound server exposes **32 tools** that group related operations by action parameter, keeping LLM context windows lean. The full granular server provides **329 individual tools** for power users. Both modes cover all 13 API object classes. MCP-level kernel actions are tracked separately in [Kernel Action Coverage](../kernels/README.md).
20
+ Every non-deprecated method in the DaVinci Resolve Scripting API is covered. The default compound server exposes **33 tools** that group related operations by action parameter, keeping LLM context windows lean. The full granular server provides **329 individual tools** for power users. Both modes cover all 13 API object classes. MCP-level kernel actions are tracked separately in [Kernel Action Coverage](../kernels/README.md).
21
+
22
+ The 33rd compound tool is `timeline_versioning` (C6) — an MCP-level workflow
23
+ tool, not a wrapper around a Resolve API method. It surfaces the
24
+ version-on-mutate hook that auto-archives the working timeline before any
25
+ destructive op, plus rollback and brain-edit history. See [SKILL.md](../SKILL.md)
26
+ for usage.
21
27
 
22
28
  Workflow helpers can go beyond one-to-one API method coverage while still using
23
29
  only public Resolve calls. For example, `media_pool.setup_multicam_timeline`