davinci-resolve-mcp 2.135.0 → 2.136.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/AGENTS.md +12 -4
- package/docs/README.md +52 -41
- package/docs/SKILL.md +1 -1
- package/docs/kernels/README.md +1 -1
- package/docs/kernels/audio-fairlight-kernel.md +1 -1
- package/docs/kernels/color-grade-kernel.md +1 -1
- package/docs/kernels/fusion-composition-kernel.md +1 -1
- package/docs/kernels/media-pool-ingest-kernel.md +1 -1
- package/docs/kernels/render-deliver-kernel.md +1 -1
- package/docs/kernels/timeline-conform-interchange-kernel.md +1 -1
- package/docs/kernels/timeline-edit-kernel.md +1 -1
- package/install.py +1 -1
- package/package.json +1 -1
- package/scripts/agent-rules/README.md +6 -4
- package/scripts/agent-rules/sync_portable_assets.py +109 -0
- package/src/granular/common.py +1 -1
- package/src/server.py +3 -3
- package/src/utils/knowledge.py +4 -18
package/AGENTS.md
CHANGED
|
@@ -66,8 +66,8 @@ semantics.
|
|
|
66
66
|
- Public overview, current stats, and docs map: `README.md`
|
|
67
67
|
- Historical release notes: `CHANGELOG.md`
|
|
68
68
|
- AI assistant operating reference: `docs/SKILL.md`
|
|
69
|
-
- Craft guidance for
|
|
70
|
-
`.
|
|
69
|
+
- Craft guidance for remote clients: the `knowledge` tool serves
|
|
70
|
+
`.agents/skills/`, `docs/guides/`, and `docs/kernels/` as resolved prose over
|
|
71
71
|
MCP. When you add a skill, guide, or kernel it is indexed automatically — a
|
|
72
72
|
drift guard fails the suite if anything in those directories is unreachable
|
|
73
73
|
- Release checklist and validation rules: `docs/process/release-process.md`
|
|
@@ -95,6 +95,12 @@ semantics.
|
|
|
95
95
|
- Installer: `install.py`
|
|
96
96
|
- Tests: `tests/`
|
|
97
97
|
- Examples: `examples/`
|
|
98
|
+
- Portable agent assets: `.agents/skills/`, `.agents/roles/`, `.agents/hooks/`
|
|
99
|
+
- Client adapters: `.claude/` and `.codex/`. Skills are byte-identical in
|
|
100
|
+
`.claude/skills/` (edit either copy, then run
|
|
101
|
+
`scripts/agent-rules/sync_portable_assets.py`); hooks are canonical in
|
|
102
|
+
`.agents/hooks/` with thin shims; `.claude/agents/*` keep their frontmatter
|
|
103
|
+
(tools/model pins) over the shared `.agents/roles/*` bodies
|
|
98
104
|
|
|
99
105
|
## Common Commands
|
|
100
106
|
|
|
@@ -130,8 +136,10 @@ for Resolve scripting; 3.13/3.14 are accepted and verified on Resolve Studio
|
|
|
130
136
|
Per-domain routers pair the live tools with their offline (advanced-server)
|
|
131
137
|
counterparts. Every domain is available on demand in ANY MCP client as a slash
|
|
132
138
|
prompt (`/color_grade_workflow`, `/timeline_edit_workflow`, `/conform_workflow`,
|
|
133
|
-
`/delivery_workflow`, `/analyze_media`) and
|
|
134
|
-
|
|
139
|
+
`/delivery_workflow`, `/analyze_media`) and as canonical skills in
|
|
140
|
+
`.agents/skills/` (Claude Code loads content-complete `.claude/skills/` copies
|
|
141
|
+
kept byte-identical by `scripts/agent-rules/sync_portable_assets.py` and its
|
|
142
|
+
parity guard). Full per-action depth lives in `docs/kernels/`.
|
|
135
143
|
|
|
136
144
|
- **Color / Grade** (`/color_grade_workflow`, skill `resolve-color`) — grading, correcting, shot matching, developing looks, or applying/modifying LUTs, CDLs, DRX grades, or copied grades. Live: timeline_item_color. Offline: drx. Depth: docs/kernels/color-grade-kernel.md + docs/guides/color-decision-guide.md.
|
|
137
145
|
- **Timeline Edit** (`/timeline_edit_workflow`, skill `resolve-edit`) — cutting, trimming, pacing, duplicating/moving clips, copying ranges, building variants, tightening a cut, or generating an editorial changelist. Live: timeline. Offline: editorial. Depth: docs/kernels/timeline-edit-kernel.md + docs/guides/editorial-decision-guide.md.
|
package/docs/README.md
CHANGED
|
@@ -41,57 +41,63 @@ ignored scratch folders such as `docs/_scratch/`.
|
|
|
41
41
|
- [Project Lifecycle](kernels/project-lifecycle-kernel.md)
|
|
42
42
|
- [Extension Authoring](kernels/extension-authoring-kernel.md)
|
|
43
43
|
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
Per-domain skills in `.
|
|
47
|
-
advanced tools automatically when an agent works in that domain.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- `resolve-
|
|
56
|
-
- `resolve-
|
|
57
|
-
- `resolve-
|
|
58
|
-
- `resolve-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
44
|
+
## Portable Agent Skills
|
|
45
|
+
|
|
46
|
+
Per-domain skills in `.agents/skills/` route craft ↔ live tools ↔ offline
|
|
47
|
+
advanced tools automatically when an agent works in that domain. This is the
|
|
48
|
+
canonical, client-neutral source. Codex discovers it directly; Claude Code loads
|
|
49
|
+
`.claude/skills/` copies that are CONTENT-COMPLETE and byte-identical to the
|
|
50
|
+
canonical files — Claude routes on the frontmatter description at selection
|
|
51
|
+
time, so a pointer stub would degrade skill routing. Edit either copy, then run
|
|
52
|
+
`scripts/agent-rules/sync_portable_assets.py`; the parity guard
|
|
53
|
+
(`tests/test_portable_asset_parity.py`) fails the suite on drift.
|
|
54
|
+
|
|
55
|
+
- `resolve-mcp` — orientation/index: the map to the domain skills below (self-trigger; not an auto-loader)
|
|
56
|
+
- `resolve-color` — grading, looks, shot match, LUT/CDL/DRX
|
|
57
|
+
- `resolve-edit` — cutting, ranges, variants, changelist
|
|
58
|
+
- `resolve-conform` — conform, relink, finishing QC, grade tracing
|
|
59
|
+
- `resolve-delivery` — render, deliverable QC, media/provenance
|
|
60
|
+
- `resolve-fusion` — Fusion comps (titles, motion graphics, VFX)
|
|
61
|
+
- `resolve-audio` — audio/Fairlight tracks, buses, loudness, sync
|
|
62
|
+
- `resolve-media-pool` — media pool ingest, organize, multicam
|
|
63
|
+
- `resolve-media-analysis` — source-safe media intelligence
|
|
64
|
+
|
|
65
|
+
Each canonical skill is a directory containing `SKILL.md`. The Claude adapter
|
|
66
|
+
uses the same directory shape because Claude Code does not discover loose files.
|
|
63
67
|
|
|
64
68
|
Two end-to-end assembly recipes sit alongside the domain skills. Where a domain
|
|
65
69
|
skill routes, these two walk a whole job:
|
|
66
70
|
|
|
67
|
-
- `resolve-rough-cut`
|
|
71
|
+
- `resolve-rough-cut` — **additive**:
|
|
68
72
|
select shots from a folder of many clips into an assembled timeline.
|
|
69
|
-
- `resolve-tighten-recording`
|
|
73
|
+
- `resolve-tighten-recording`
|
|
70
74
|
— **subtractive**: remove dead air from one long single-take recording.
|
|
71
75
|
|
|
72
76
|
Three more sit outside the domain routing:
|
|
73
77
|
|
|
74
|
-
- `house-style`
|
|
75
|
-
corrections, so the same note is not given twice.
|
|
78
|
+
- `house-style` — accumulated editorial
|
|
79
|
+
corrections, so the same note is not given twice. Append to it
|
|
76
80
|
when an editorial decision is corrected.
|
|
77
|
-
- `resolve-session`
|
|
81
|
+
- `resolve-session` — `/resolve-session`
|
|
78
82
|
connects, confirms edition and bridge, and reports project/timeline/pool state.
|
|
79
|
-
- `release-check`
|
|
83
|
+
- `release-check` — `/release-check`
|
|
80
84
|
walks a version bump using [docs/process/release-process.md](process/release-process.md)
|
|
81
85
|
as the sole source; the skill wraps that doc, it does not duplicate it.
|
|
82
86
|
|
|
83
87
|
The offline half of every one is the advanced server; see
|
|
84
88
|
[Advanced Server](../resolve-advanced/README.md).
|
|
85
89
|
|
|
86
|
-
##
|
|
90
|
+
## Portable Hooks and Reviewers
|
|
87
91
|
|
|
88
|
-
Four hooks live in `.
|
|
89
|
-
`AGENTS.md` states in prose, and two `PostToolUse` checks that
|
|
90
|
-
engineering drift
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
Four canonical hooks live in `.agents/hooks/` — two `PreToolUse` guards
|
|
93
|
+
enforcing rules `AGENTS.md` states in prose, and two `PostToolUse` checks that
|
|
94
|
+
surface engineering drift immediately after the edit that caused it. Thin
|
|
95
|
+
wrappers in `.claude/hooks/` and `.codex/hooks/` translate only the host
|
|
96
|
+
protocol; policy stays in the canonical scripts.
|
|
97
|
+
|
|
98
|
+
Codex wiring is committed in `.codex/hooks.json`. Because project hooks execute
|
|
99
|
+
commands, review and trust that file through Codex's `/hooks` UI. Claude Code
|
|
100
|
+
users opt in by adding this block to `.claude/settings.local.json`:
|
|
95
101
|
|
|
96
102
|
```json
|
|
97
103
|
{
|
|
@@ -139,18 +145,18 @@ yours):
|
|
|
139
145
|
}
|
|
140
146
|
```
|
|
141
147
|
|
|
142
|
-
Hooks are read at session start, so restart
|
|
143
|
-
four are:
|
|
148
|
+
Hooks are read at session start, so restart the client after enabling them. The
|
|
149
|
+
four canonical policies are:
|
|
144
150
|
|
|
145
|
-
- `.
|
|
151
|
+
- `.agents/hooks/frame_verification_guard.py` — denies grade-applying actions on
|
|
146
152
|
`timeline_item_color` until the session has actually looked at a
|
|
147
153
|
Resolve-rendered frame, and asks before whole-grade artifacts
|
|
148
154
|
(`safe_copy_grade`, `bulk_match_to_hero`) overwrite hand-work. `dry_run`
|
|
149
155
|
passes through untouched.
|
|
150
|
-
- `.
|
|
156
|
+
- `.agents/hooks/source_media_guard.py` — denies shell commands that write,
|
|
151
157
|
move, or delete source media outside a scratch root. Reads (`ffprobe`, and
|
|
152
158
|
`ffmpeg` writing into scratch) pass.
|
|
153
|
-
- `.
|
|
159
|
+
- `.agents/hooks/agent_rules_drift_check.py` — after an edit to anything
|
|
154
160
|
`generate.mjs` reads (`docs/SKILL.md`, `docs/kernels/README.md`,
|
|
155
161
|
`resolve-advanced/README.md`, and `generate.mjs` itself, which carries the
|
|
156
162
|
DOMAINS manifest inline) or to `AGENTS.md`, which it writes, runs
|
|
@@ -160,7 +166,7 @@ four are:
|
|
|
160
166
|
blocks. Skips quietly if `node` isn't on `PATH`. **If `generate.mjs` grows a
|
|
161
167
|
new input, add it to `SOURCE_PATHS` in the hook** — an unwatched input is a
|
|
162
168
|
silent hook on exactly the edit it exists to catch.
|
|
163
|
-
- `.
|
|
169
|
+
- `.agents/hooks/run_matching_test.py` — after an edit to `src/<module>.py`,
|
|
164
170
|
runs the matching `tests/test_<module>.py` if one exists, using the project
|
|
165
171
|
venv (`venv/bin/python`) so `pytest` is actually importable. Informational
|
|
166
172
|
only; skips quietly if there's no matching test file or no working `pytest`.
|
|
@@ -169,8 +175,13 @@ four are:
|
|
|
169
175
|
for `src/server.py` or `src/granular/common.py`. Silence means "no matching
|
|
170
176
|
test file", not "this edit is fine".
|
|
171
177
|
|
|
172
|
-
|
|
173
|
-
|
|
178
|
+
Codex does not currently support an interactive `ask` result from `PreToolUse`.
|
|
179
|
+
For the two whole-grade actions, its adapter adds a warning while the MCP
|
|
180
|
+
server's confirmation-token gate remains authoritative. Hard denials, including
|
|
181
|
+
missing frame evidence and source-media writes, block in both clients.
|
|
182
|
+
|
|
183
|
+
Three canonical reviewer roles live in `.agents/roles/`, with native Codex
|
|
184
|
+
definitions under `.codex/agents/` and Claude adapters under `.claude/agents/`:
|
|
174
185
|
|
|
175
186
|
- `cut-reviewer` — screens an assembled timeline from its frames and reports on
|
|
176
187
|
pacing, shot order, continuity, and coverage gaps.
|
package/docs/SKILL.md
CHANGED
|
@@ -207,7 +207,7 @@ Operating rules an agent must know:
|
|
|
207
207
|
|
|
208
208
|
Per-domain depth for both servers lives in the kernels (`docs/kernels/`), each of
|
|
209
209
|
which carries an "Advanced (offline) server" section where an offline counterpart
|
|
210
|
-
exists.
|
|
210
|
+
exists. Portable skills in `.agents/skills/` (`resolve-color`, `resolve-edit`,
|
|
211
211
|
`resolve-conform`, `resolve-delivery`, `resolve-media-analysis`) route
|
|
212
212
|
craft ↔ live ↔ offline automatically when working in that domain.
|
|
213
213
|
|
package/docs/kernels/README.md
CHANGED
|
@@ -38,7 +38,7 @@ two:
|
|
|
38
38
|
- Timeline Edit → `editorial` (interchange + changelist), `drt`
|
|
39
39
|
|
|
40
40
|
Per-domain Claude Code skills route craft ↔ live ↔ offline automatically and live
|
|
41
|
-
in `.
|
|
41
|
+
in `.agents/skills/`: `resolve-color`, `resolve-edit`, `resolve-conform`,
|
|
42
42
|
`resolve-delivery` (plus `resolve-media-analysis`). `docs/SKILL.md` is the
|
|
43
43
|
top-level brief for both servers.
|
|
44
44
|
|
|
@@ -121,7 +121,7 @@ patches audio **offline, no Resolve running**:
|
|
|
121
121
|
|
|
122
122
|
Rule of thumb: plan/measure offline, apply mix/track changes live; use
|
|
123
123
|
`fairlight` for bus work the scripting API can't reach. See the `resolve-audio`
|
|
124
|
-
skill (`.
|
|
124
|
+
skill (`.agents/skills/resolve-audio/SKILL.md`) and the `/audio_workflow` prompt.
|
|
125
125
|
|
|
126
126
|
## Live Probe
|
|
127
127
|
|
|
@@ -156,7 +156,7 @@ Cross-server rules an agent must know:
|
|
|
156
156
|
- **Deps.** The grading catalog needs `sharp`; call the advanced `capabilities`
|
|
157
157
|
tool for live status and install hints.
|
|
158
158
|
|
|
159
|
-
See the `resolve-color` skill (`.
|
|
159
|
+
See the `resolve-color` skill (`.agents/skills/resolve-color/SKILL.md`) for the
|
|
160
160
|
craft ↔ live ↔ offline routing and the frame-first rule.
|
|
161
161
|
|
|
162
162
|
## Live Probe
|
|
@@ -119,7 +119,7 @@ running**, via the `fusion` tool:
|
|
|
119
119
|
Rule of thumb: author and verify the comp offline, then apply it live with
|
|
120
120
|
`fusion_comp` `safe_add_tool` → `safe_set_inputs` → `safe_connect_tools` (the
|
|
121
121
|
`to_api_calls` output maps directly onto those). See the `resolve-fusion` skill
|
|
122
|
-
(`.
|
|
122
|
+
(`.agents/skills/resolve-fusion/SKILL.md`) and the `/fusion_workflow` prompt.
|
|
123
123
|
|
|
124
124
|
## Live Probe
|
|
125
125
|
|
|
@@ -137,7 +137,7 @@ actions):
|
|
|
137
137
|
Rule of thumb: verify and inventory the card offline *before* importing, then
|
|
138
138
|
import/organize live. `media` also serves the delivery side (see the
|
|
139
139
|
`resolve-delivery` skill). See the `resolve-media-pool` skill
|
|
140
|
-
(`.
|
|
140
|
+
(`.agents/skills/resolve-media-pool/SKILL.md`) and the `/media_pool_workflow` prompt. Never
|
|
141
141
|
rename or derive camera originals without explicit approval.
|
|
142
142
|
|
|
143
143
|
## Live Evidence
|
|
@@ -135,7 +135,7 @@ Rules an agent must know:
|
|
|
135
135
|
- **Deps.** `deliverable`/`media` QC needs **ffmpeg + ffprobe on PATH** (GPL, not
|
|
136
136
|
bundled) — call the advanced `capabilities` tool for status + install hints.
|
|
137
137
|
|
|
138
|
-
See the `resolve-delivery` skill (`.
|
|
138
|
+
See the `resolve-delivery` skill (`.agents/skills/resolve-delivery/SKILL.md`) for the
|
|
139
139
|
craft ↔ live ↔ offline routing.
|
|
140
140
|
|
|
141
141
|
## Live Evidence
|
|
@@ -160,7 +160,7 @@ Gotchas the live path shares:
|
|
|
160
160
|
- **Deps.** `better-sqlite3` gates lineage/reverse/DB; `sharp`/ffmpeg gate frame
|
|
161
161
|
compare — call the advanced `capabilities` tool.
|
|
162
162
|
|
|
163
|
-
See the `resolve-conform` skill (`.
|
|
163
|
+
See the `resolve-conform` skill (`.agents/skills/resolve-conform/SKILL.md`) for the
|
|
164
164
|
craft ↔ live ↔ offline routing.
|
|
165
165
|
|
|
166
166
|
## Live Probe
|
|
@@ -196,7 +196,7 @@ Use these to answer "what changed between v3 and v4" or to hand a conform an
|
|
|
196
196
|
accurate change list without opening either timeline. For conforming/relinking
|
|
197
197
|
that change list, see the Timeline Conform / Interchange kernel and the
|
|
198
198
|
`resolve-conform` skill; for the edit ↔ offline routing, see the `resolve-edit`
|
|
199
|
-
skill (`.
|
|
199
|
+
skill (`.agents/skills/resolve-edit/SKILL.md`).
|
|
200
200
|
|
|
201
201
|
## Development Guardrails
|
|
202
202
|
|
package/install.py
CHANGED
|
@@ -37,7 +37,7 @@ from src.utils.update_check import (
|
|
|
37
37
|
|
|
38
38
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
39
39
|
|
|
40
|
-
VERSION = "2.
|
|
40
|
+
VERSION = "2.136.0"
|
|
41
41
|
# Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
|
|
42
42
|
# Resolve's scripting bridge loads into newer interpreters on recent builds
|
|
43
43
|
# (Python 3.14 verified against Resolve Studio 20.3.2). Older Resolve builds
|
package/package.json
CHANGED
|
@@ -24,7 +24,8 @@ cannot drift.
|
|
|
24
24
|
| Platform | File(s) | Trigger | Source |
|
|
25
25
|
|---|---|---|---|
|
|
26
26
|
| Codex / OpenCode / Zed / others | `AGENTS.md` (`## Domain Routing` block) | always-on | generated block |
|
|
27
|
-
|
|
|
27
|
+
| Codex and compatible agents | `.agents/skills/<name>/SKILL.md` | semantic (description) | hand-authored canonical skill |
|
|
28
|
+
| Claude Code | `.claude/skills/<name>/SKILL.md` | semantic (description) | thin adapter to canonical skill |
|
|
28
29
|
| Cursor | `.cursor/rules/*.mdc` | `alwaysApply` repo rule + per-domain `description` (agent-requested) | generated |
|
|
29
30
|
| VS Code / Copilot | `.github/copilot-instructions.md` + `.github/instructions/*.instructions.md` | always-on + `applyTo` | generated |
|
|
30
31
|
| Windsurf | `.windsurf/rules/*.md` + `.windsurfrules` | rules dir + legacy flat | generated |
|
|
@@ -33,8 +34,9 @@ cannot drift.
|
|
|
33
34
|
| Continue | `.continue/rules/resolve-mcp.md` | always-on | generated |
|
|
34
35
|
| Claude Desktop | — (chat client, no repo rules) | — | MCP prompts only |
|
|
35
36
|
|
|
36
|
-
`.
|
|
37
|
-
|
|
37
|
+
`.agents/skills/*` stays hand-authored as the canonical rich skill source.
|
|
38
|
+
`.claude/skills/*` contains only compatibility adapters. Each skill is a
|
|
39
|
+
**directory** holding a `SKILL.md` named for its frontmatter `name`;
|
|
38
40
|
a loose `.md` at the top level of `.claude/skills/` is never discovered and
|
|
39
41
|
fails silently. Every
|
|
40
42
|
other file is generated. `AGENTS.md` remains the universal backstop for any
|
|
@@ -65,7 +67,7 @@ node scripts/agent-rules/generate.mjs --check # exit 1 if anything is stale (C
|
|
|
65
67
|
|
|
66
68
|
- **New domain:** add an entry to `DOMAINS` in `generate.mjs`, add a matching
|
|
67
69
|
`@mcp.prompt` in `src/server.py`, and (optionally) a rich
|
|
68
|
-
`.
|
|
70
|
+
`.agents/skills/<name>/SKILL.md` and add/update its client adapter. Regenerate.
|
|
69
71
|
- **New platform:** add an `emit(...)` for its convention in `generate.mjs`,
|
|
70
72
|
reusing `domainBody(d)` / `repoHygiene`. Regenerate. Do not hand-edit generated
|
|
71
73
|
files — the drift guard will fail.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Sync the portable agent assets (`.agents/`) with their Claude adapters.
|
|
3
|
+
|
|
4
|
+
The layout contract (adapted from PR #173):
|
|
5
|
+
|
|
6
|
+
- `.agents/skills/*/SKILL.md` is the canonical, host-neutral skill corpus —
|
|
7
|
+
the `knowledge` MCP tool serves it, and non-Claude hosts read it directly.
|
|
8
|
+
- `.claude/skills/*/SKILL.md` is a CONTENT-COMPLETE copy, byte-identical to
|
|
9
|
+
the canonical file. Claude Code routes on the frontmatter description at
|
|
10
|
+
selection time, so the adapter must carry the full text — a pointer stub
|
|
11
|
+
would cost a read per invocation and hide the trigger phrasing.
|
|
12
|
+
- `.agents/roles/*.md` is the body (frontmatter stripped) of the matching
|
|
13
|
+
`.claude/agents/*.md`. The Claude file keeps its frontmatter — name,
|
|
14
|
+
description, tools, and the deliberate `model:` pin — which host-neutral
|
|
15
|
+
role files cannot carry.
|
|
16
|
+
- `.agents/hooks/*.py` is canonical executable logic; `.claude/hooks` and
|
|
17
|
+
`.codex/hooks` are thin runpy shims (execution-only surfaces need no
|
|
18
|
+
content duplication).
|
|
19
|
+
|
|
20
|
+
Edit EITHER side of a skill (they are identical); edit `.claude/agents` for
|
|
21
|
+
roles. Then run this script to restore the invariant:
|
|
22
|
+
|
|
23
|
+
venv/bin/python scripts/agent-rules/sync_portable_assets.py # write
|
|
24
|
+
venv/bin/python scripts/agent-rules/sync_portable_assets.py --check # verify only
|
|
25
|
+
|
|
26
|
+
`tests/test_portable_asset_parity.py` fails the suite when the invariant is
|
|
27
|
+
broken, so drift cannot land.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import argparse
|
|
33
|
+
import re
|
|
34
|
+
import sys
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
|
|
37
|
+
REPO = Path(__file__).resolve().parents[2]
|
|
38
|
+
CLAUDE_SKILLS = REPO / ".claude" / "skills"
|
|
39
|
+
AGENT_SKILLS = REPO / ".agents" / "skills"
|
|
40
|
+
CLAUDE_AGENTS = REPO / ".claude" / "agents"
|
|
41
|
+
AGENT_ROLES = REPO / ".agents" / "roles"
|
|
42
|
+
|
|
43
|
+
_FRONTMATTER_RE = re.compile(r"^---\n.*?\n---\n\n?", re.S)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def strip_frontmatter(text: str) -> str:
|
|
47
|
+
m = _FRONTMATTER_RE.match(text)
|
|
48
|
+
return text[m.end():] if m else text
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def skill_pairs():
|
|
52
|
+
names = sorted(
|
|
53
|
+
{p.parent.name for p in CLAUDE_SKILLS.glob("*/SKILL.md")}
|
|
54
|
+
| {p.parent.name for p in AGENT_SKILLS.glob("*/SKILL.md")}
|
|
55
|
+
)
|
|
56
|
+
for name in names:
|
|
57
|
+
yield name, CLAUDE_SKILLS / name / "SKILL.md", AGENT_SKILLS / name / "SKILL.md"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def role_pairs():
|
|
61
|
+
names = sorted(
|
|
62
|
+
{p.stem for p in CLAUDE_AGENTS.glob("*.md")} | {p.stem for p in AGENT_ROLES.glob("*.md")}
|
|
63
|
+
)
|
|
64
|
+
for name in names:
|
|
65
|
+
yield name, CLAUDE_AGENTS / f"{name}.md", AGENT_ROLES / f"{name}.md"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def run(check_only: bool) -> int:
|
|
69
|
+
problems: list[str] = []
|
|
70
|
+
for name, claude_p, agent_p in skill_pairs():
|
|
71
|
+
if not claude_p.exists():
|
|
72
|
+
problems.append(f"skill '{name}': canonical exists but .claude adapter is missing — it would never load in Claude Code")
|
|
73
|
+
if not check_only and agent_p.exists():
|
|
74
|
+
claude_p.parent.mkdir(parents=True, exist_ok=True)
|
|
75
|
+
claude_p.write_text(agent_p.read_text())
|
|
76
|
+
continue
|
|
77
|
+
src = claude_p.read_text()
|
|
78
|
+
if not agent_p.exists() or agent_p.read_text() != src:
|
|
79
|
+
problems.append(f"skill '{name}': .agents copy {'missing' if not agent_p.exists() else 'differs'}")
|
|
80
|
+
if not check_only:
|
|
81
|
+
agent_p.parent.mkdir(parents=True, exist_ok=True)
|
|
82
|
+
agent_p.write_text(src)
|
|
83
|
+
for name, claude_p, role_p in role_pairs():
|
|
84
|
+
if not claude_p.exists():
|
|
85
|
+
problems.append(f"role '{name}': .agents/roles exists but .claude/agents is missing — restore the frontmatter file by hand (it carries tools/model pins this script cannot invent)")
|
|
86
|
+
continue
|
|
87
|
+
body = strip_frontmatter(claude_p.read_text())
|
|
88
|
+
if not role_p.exists() or role_p.read_text() != body:
|
|
89
|
+
problems.append(f"role '{name}': .agents/roles {'missing' if not role_p.exists() else 'differs from the .claude/agents body'}")
|
|
90
|
+
if not check_only:
|
|
91
|
+
role_p.parent.mkdir(parents=True, exist_ok=True)
|
|
92
|
+
role_p.write_text(body)
|
|
93
|
+
if problems:
|
|
94
|
+
for p in problems:
|
|
95
|
+
print(("DRIFT: " if check_only else "SYNCED: ") + p)
|
|
96
|
+
return 1 if check_only else 0
|
|
97
|
+
print("portable assets in sync")
|
|
98
|
+
return 0
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def main() -> int:
|
|
102
|
+
ap = argparse.ArgumentParser(description=__doc__)
|
|
103
|
+
ap.add_argument("--check", action="store_true", help="verify only; non-zero exit on drift")
|
|
104
|
+
args = ap.parse_args()
|
|
105
|
+
return run(check_only=args.check)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if __name__ == "__main__":
|
|
109
|
+
sys.exit(main())
|
package/src/granular/common.py
CHANGED
|
@@ -87,7 +87,7 @@ if not logging.getLogger().handlers:
|
|
|
87
87
|
handlers=[logging.StreamHandler()],
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
-
VERSION = "2.
|
|
90
|
+
VERSION = "2.136.0"
|
|
91
91
|
logger = logging.getLogger("davinci-resolve-mcp")
|
|
92
92
|
logger.info(f"Starting DaVinci Resolve MCP Server v{VERSION}")
|
|
93
93
|
logger.info(f"Detected platform: {get_platform()}")
|
package/src/server.py
CHANGED
|
@@ -11,7 +11,7 @@ Usage:
|
|
|
11
11
|
python src/server.py --full # Start the 353-tool granular server instead
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
VERSION = "2.
|
|
14
|
+
VERSION = "2.136.0"
|
|
15
15
|
|
|
16
16
|
import base64
|
|
17
17
|
import os
|
|
@@ -545,8 +545,8 @@ def prep_color_handoff(output_dir: str = "") -> str:
|
|
|
545
545
|
# ─── Per-domain workflow routers ───────────────────────────────────────────────
|
|
546
546
|
# Cross-platform depth: these surface as slash commands in EVERY MCP client
|
|
547
547
|
# (Codex, Cursor, Copilot, Continue, Claude Desktop, …), so per-domain routing is
|
|
548
|
-
# not limited to
|
|
549
|
-
# same name; keep them in sync with docs/kernels/*.
|
|
548
|
+
# not limited to one client's adapters. They mirror the canonical `.agents/skills/`
|
|
549
|
+
# skills of the same name; keep them in sync with docs/kernels/*.
|
|
550
550
|
|
|
551
551
|
|
|
552
552
|
@mcp.prompt(
|
package/src/utils/knowledge.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This repository carries a real body of craft guidance: how to tighten a recording
|
|
4
4
|
without cutting the breath out of it, what to look at before applying a grade, which
|
|
5
|
-
Resolve API calls silently lie. It lives in two places — `.
|
|
5
|
+
Resolve API calls silently lie. It lives in two places — `.agents/skills/*/SKILL.md`
|
|
6
6
|
and `docs/guides` + `docs/kernels` — and until now both were reachable only by an
|
|
7
7
|
agent that could open files in this checkout.
|
|
8
8
|
|
|
@@ -57,7 +57,7 @@ from pathlib import Path
|
|
|
57
57
|
from typing import Any, Dict, List, Optional, Tuple
|
|
58
58
|
|
|
59
59
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
60
|
-
SKILLS_DIR = REPO_ROOT / ".
|
|
60
|
+
SKILLS_DIR = REPO_ROOT / ".agents" / "skills"
|
|
61
61
|
GUIDES_DIR = REPO_ROOT / "docs" / "guides"
|
|
62
62
|
KERNELS_DIR = REPO_ROOT / "docs" / "kernels"
|
|
63
63
|
|
|
@@ -217,24 +217,10 @@ def _first_paragraph(body: str) -> str:
|
|
|
217
217
|
def _title_of(body: str, fallback: str) -> str:
|
|
218
218
|
for line in body.splitlines():
|
|
219
219
|
if line.startswith("# "):
|
|
220
|
-
|
|
221
|
-
# client. The subject is everything before the dash.
|
|
222
|
-
title = line[2:].strip()
|
|
223
|
-
return re.sub(r"\s*[—-]\s*Claude Code Skill\s*$", "", title).strip()
|
|
220
|
+
return line[2:].strip()
|
|
224
221
|
return fallback
|
|
225
222
|
|
|
226
223
|
|
|
227
|
-
def _strip_client_scaffolding(body: str) -> str:
|
|
228
|
-
"""Drop the one H1 that names a specific client. Prose is left alone."""
|
|
229
|
-
return re.sub(
|
|
230
|
-
r"^#\s+(.*?)\s*[—-]\s*Claude Code Skill\s*$",
|
|
231
|
-
lambda m: f"# {m.group(1)}",
|
|
232
|
-
body,
|
|
233
|
-
count=1,
|
|
234
|
-
flags=re.M,
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
|
|
238
224
|
_DOC_REF_RE = re.compile(r"`(docs/[^`\s]+\.md)`|\]\((docs/[^)\s]+\.md)\)")
|
|
239
225
|
|
|
240
226
|
|
|
@@ -275,7 +261,7 @@ def _build_index() -> Dict[str, Dict[str, Any]]:
|
|
|
275
261
|
"summary": fields.get("description", "") or _first_paragraph(body),
|
|
276
262
|
"category": "repo" if topic in _REPO_SKILLS else "workflow",
|
|
277
263
|
"path": str(skill_md.relative_to(REPO_ROOT)),
|
|
278
|
-
"body":
|
|
264
|
+
"body": body.strip(),
|
|
279
265
|
}
|
|
280
266
|
|
|
281
267
|
for category, directory in (("guide", GUIDES_DIR), ("kernel", KERNELS_DIR)):
|