# Changelog All notable changes to **tdmcp** are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [0.13.2] - 2026-08-11 This patch release realigns the package, bridge, manifests, bootstrap URLs and release artifacts after the v0.13.1 npm/source divergence, and includes the post-v0.13.1 mainline work below. ### Added - **Bounded live authored-code search** — added `search_td_code` and the structured `POST /api/code/search` bridge route for deterministic lexical discovery across DAT bodies and parameter expressions. Results use redaction-before-match, bounded excerpts, explicit scan/completeness metadata, and hard node/document/parameter/byte/time budgets; the read-only path remains available with raw bridge execution disabled. The tool is also exposed through the safe and directory profiles, local copilot, and `tdmcp-agent code search`, with English and Portuguese documentation. Live TouchDesigner validation remains explicitly pending. - **Agent-oriented documentation discovery** — the VitePress site now generates a SHA-256-verified Agent Skills index from canonical curated skills, advertises page-level discovery and Markdown alternates, and registers read-only WebMCP documentation search and lookup tools. Generated skill output is cleared and rebuilt per build so renamed or removed skills cannot remain published, and WebMCP executors enforce their closed input schemas. - **Authenticated one-request operation closure (Wave 16)** — live QA on the isolated TouchDesigner 099 build 2025.32820 process at PID 62916 passed A0–A13 with bridge exec disabled: authenticated operation preview/commit/receipt, exact journal observation, native Undo/Redo, induced rollback, artist-drift refusal, response-loss/timeout/disconnect replay, same- and different-key concurrency, reload authority loss, preservation of the legacy per-REST undo wrapper, final cleanup and health checks. The first A4 run exposed that created-node intrinsic position was missing from the journal snapshot; journal v2 now includes final created intrinsic state, and the repeated A4 correctly reports `drifted` and refuses the guarded Undo. An earlier phase-2 harness run also recorded a port-reuse `OSError`; the bounded per-phase-port rerun passed A5–A9. The receipt-authorized exact-state safe- revert core passed direct live apply/revert/replay, native Undo/Redo of the compensating operation and zero-write drift refusal, but remains internal and unregistered: no route, typed client, broker approval or MCP tool was added. Selection-to-component is a live **NO-GO** because Redo was not exact and an induced failure left an orphan redo item; the artist-facing agent turn remains **HOLD** pending operation-specific Apply/Keep authority binding. This proves one bounded structured request only: arbitrary multi-request MCP atomicity and any default migration remain blocked and are not promoted by this release. - **Receipt-authorized operation boundary (Wave 15)** — added token-required structured bridge/client methods for bounded operation preview, one-request commit and capability-authorized terminal receipt lookup with fresh exact journal observation. The route family works with `TDMCP_BRIDGE_ALLOW_EXEC=0`, is excluded from the generic per-REST undo wrapper, never exposes an idempotency key as recovery authority and retains no bearer token. TypeScript/Python receipts now agree on `receipt_capability`; shared golden tests cover the complete authority envelope, and journal capacity fails before mutation instead of evicting a still-authorized record. No MCP tool, CLI command, generic undo/redo or receipt-bound revert was registered. A disposable second TD process remained in application loading without a bridge listener and was terminated by exact PID while the artist process stayed alive, so public controller response-loss/reload/concurrency and the proposed compensation journal remain **UNVERIFIED**. Generic native undo/redo is a permanent no-go because repeatable stack labels cannot prevent same-label ABA; selection-to-component and plan/preview/commit agent orchestration remain probe-gated. - **Live closure and trust-boundary hardening (Wave 14)** — live QA on a separately identified disposable TD 099 build 2025.32820 passed `tdmcp show` Perform entry, already-on idempotency and ambiguous-readback rollback; OAuth's TD callback transport passed Allow, Deny, timeout, close and disconnect fail-closed behavior with bridge exec disabled. The internal, still-unregistered one-request operation adapter passed commit, one callback-journal entry, native undo/redo and reverse rollback after an induced incompatible connection. This does **not** promote a public operation route or change the per-REST undo default: timeout, cancellation, disconnect/reload and multi-request composition remain held, and public one-item undo/redo still lacks a stable native history identity. The optional `enhance_build.visualCritique` product path is integrated with exact model/fixture gates, bounded preview, Apply/Keep consent, proposal-bound CAS and compensating restore. Live exact-model QA proposed and committed `fontsizex` `16 -> 32`, verified the same-model after-preview and native undo label, then separately committed `32 -> 48` and restored to `32` without logging the restore capability. Invalid model output and interaction timeout/Keep both remained zero-write fail-closed paths. Release automation now separates read-only validation from optional publication, gives GitHub CLI explicit repository context, gates npm publication at job scope and shares one `release:check` lifecycle. Additional closures add a shared TypeScript/Python operation corpus, direct 413 bridge-body tests and live Web Server DAT evidence, nav-derived EN/PT availability with package- version provenance, bounded OAuth per-source fairness under a global ceiling, complete vision-egress allow/deny/redaction tests, and PID/project/port safety rules that forbid guessed TouchDesigner flags and ambiguous multi-process GUI automation. Production OAuth HTTPS, a physical UI click, headless/other-build TD, other model/build combinations and hosted workflow execution remain explicit follow-ups. - **Vision runtime proof (Wave 13)** — installed the explicitly approved local `qwen3-vl:8b-instruct-q4_K_M` runtime model and recorded its exact Ollama digest, Q4_K_M quantization and native `vision` / `tools` capabilities. After hardening the synthetic contract, calibration suite `2026-07-15.3` passed every tool capability plus `image_input`, producing an exact mutation-eligible cache entry. The hardened contract uses a valid non-answer-bearing split-color PNG, bounded streamed native metadata and typed timeout/capability failures. A strict offline good/bad surrogate then passed 6/6 with locally derived scores 91 versus 43 under unchanged weights and thresholds. This is still pre-product evidence: authenticated TD-generated fixture TOPs and a disposable TouchDesigner bridge remain unverified, so no visual mutation tool or route was registered. - **Internal operation-plan hardening (Wave 13)** — the unregistered whole-operation foundation now derives an exact scalar CAS contract for requested parameter style/mode/value/writability, metadata values/writability and bilateral connector occupancy, including ordered connect/disconnect simulation. Missing, extra, readonly or drifted facts fail before adapter eligibility or writes. Snapshot build/project/owner identities are bounded and collision-checked; terminal receipts require contiguous result coverage, unique in-scope paths, exact rollback-error/result correspondence and coherent journal/replay state. Public text/body accounting is aligned to UTF-8 bytes across TypeScript and Python, including rejection of lone surrogates, and the design now reflects the adapter-less `unverified_for_allowlist` / `journal_eligible=false` default and private process-local adapter identity. No route, public client, tool or undo default was added; the live snapshot/transaction/journal/replay matrix and authority-bound receipt lookup remain **UNVERIFIED**. - **TD-native Interaction & Safety Wave 12** — extended the existing read-only `plan_visual` tool with an explicit `planner: "llm"` mode. The deterministic planner remains the default and fallback. The opt-in path makes at most one bounded completion, supplies only compact redacted editor/project/recipe/operator evidence, validates every proposed tool, recipe and operator against the actual registries, and never mutates TouchDesigner. Added the `tdmcp show ` command: it binds one exact profile/config, runs runtime status, doctor and preflight, requires separate consent for WARN and optional UNVERIFIED results, and uses one Perform Mode write plus bounded readback/rollback without loading a project or falling back to raw Python. Its offline contract passes; live TouchDesigner entry/readback/rollback is **UNVERIFIED — pending a safe disposable sandbox**, so this command is not claimed as released or live- proven. - **OAuth DCR lifecycle hardening (Wave 12)** — public registered clients now have a seven-day default inactivity lifetime; inactive tokenless rows are pruned, capacity pressure evicts the oldest tokenless row, and clients with live security-relevant token rows are retained. The global unauthenticated registration limiter is now a continuously refilling token bucket instead of a fixed window. Per-source fairness remains intentionally unclaimed until the HTTP deployment has a trusted-proxy client-identity contract; spoofed forwarded headers are not trusted. - **Internal operation-plan foundation (Wave 12)** — added bounded plan/preview/commit validation, stateless HMAC preview capabilities, commit-time compare-and-swap, callback-journal receipts and rollback invariants for a future one-request mutation boundary. It has no controller route, TD client method, CLI command, MCP registry entry or public tool, and commit fails closed with `unverified_live_boundary` without the exact live-verified in-process adapter. Whole-tool undo remains held; this internal offline foundation is not a live or public capability. - **Remote Connection Trust Wave 11** — added opt-in Streamable HTTP OAuth authorization-code flow with required S256 PKCE, path-specific protected-resource discovery, bounded public-client DCR, rotating refresh tokens and exact resource/scope binding. The co-located Node process owns codes/tokens and binds each MCP session to its authenticated client principal; TouchDesigner receives only one bounded **Allow / Deny** display transaction through authenticated structured routes that remain usable with `TDMCP_BRIDGE_ALLOW_EXEC=0`. Close, timeout, disconnect, duplicate consumption, Perform/headless UI and bridge errors deny. Owner-private durable state stores token HMAC digests, never raw tokens. Existing HTTP behavior stays compatible through `TDMCP_HTTP_AUTH_MODE=auto`; OAuth is opt-in, invalid auth combinations fail startup, and legacy bearer coexistence requires explicit `hybrid`. Offline unit/integration, auth-downgrade and session-isolation tests pass. Final integrated TD-native and production-HTTPS evidence remains **UNVERIFIED**; DCR is supported, while CIMD and multi-user/federated identity remain follow-ups. - **Artist Workspace Control & Exact Placement Wave 10** — extended `arrange_network` with additive `layout_mode: "explicit"` for bounded, fingerprinted exact placement with dock-host precedence, one-request readback/rollback and legacy-compatible automatic defaults. Added `manage_artist_workspace` for one temporary, bridge-owned Network Editor plus TOP/PANEL viewer lifecycle with next-frame main-thread scheduling, bounded polling, idempotency, lease/capacity limits and compare-and-swap restoration. Both structured paths work with `TDMCP_BRIDGE_ALLOW_EXEC=0`, and integrated offline schemas, route contracts, rollback/state-machine tests and generated catalogs pass. Authenticated live QA on TD 099 build 2025.32820 passed placement apply/replay/undo/redo, TOP workspace open/active/restore and PANEL workspace open/active/cancel, with verified cleanup, `undo_label: null`, auth refusal and bounded-input refusal. The first three-readback workspace attempt failed closed and compensated; a 12-readback window then exposed later drift from an animated Network Editor `home()`. The final path removes that unnecessary animation, keeps the bounded stable-fingerprint guard, and passed a fresh TOP restore whose baseline viewport remained unchanged after one second. Terminal no-op restore keys did not grow the idempotency map, and no new `THREAD CONFLICT` appeared. Live conflict, timeout/lease/Perform edges, headless TD, other builds and platforms remain **UNVERIFIED**. The bounded visual-critique loop remains **HOLD / UNVERIFIED**. Wave 13 later added an explicitly approved, exact-digest vision runtime and synthetic calibration PASS, but the feature-specific perceptual and disposable-TD gates remain incomplete; no visual tool, route or mutation path was added. - **Portable Artifact Trust & Annotation-Aware Composition Wave 9** — extended five existing surfaces without increasing the tool count. `validate_library_asset` can perform an authenticated quarantine-only deep TOX round-trip with bounded PASS/FAIL/UNVERIFIED contract, delayed-cook and cleanup evidence. `make_portable_tox` records canonical non-self- referential provenance by default, adds an opt-in clean-Git policy and exact- build installed help snapshots, and promotes artifact/provenance recoverably after native overwrite consent. `attach_docs_as_assets` can refresh that help snapshot and its provenance manifest hash. `manage_annotation action:"edit"` adds structured transactional Annotate COMP title/body/RGBA/bounds edits, and `arrange_network annotation_aware:true` preserves annotated groups, docked deltas and optional exact padded bounds through fingerprinted structured context/apply routes. Authenticated live QA passed on TD 099 build 2025.32820 with `TDMCP_BRIDGE_ALLOW_EXEC=0`; actual headless TD and other builds remain **UNVERIFIED**. - **Live Closure & Native History Safety Wave 8** — closed the authenticated current-build route matrix for editor insertion, transactional TOX export, package reconciliation and custom-parameter lifecycle with `TDMCP_BRIDGE_ALLOW_EXEC=0`. Live fixes use structural connector/ParGroup identity, resolve the imported parameter mode enum without `td.ParMode`, order clamp/value edits deterministically, align package consent fingerprints on `OPType`, treat TD stacks as newest-first, and report actual native undo names separately from requested wrapper labels. A final identity probe rejected public `undo_redo_td_action`: the native stack returns fresh plain strings, repeated labels are indistinguishable, and same-label ABA could undo an intervening artist action. One-item automation and whole-tool undo across requests therefore remain **FAIL / HELD**; actual headless TD and other builds remain **UNVERIFIED**. - **TD-native Interaction & Safety Wave 1** — added an authenticated, bounded, exactly-once native decision broker with a next-frame, non-modal TouchDesigner inbox; `delete_td_node` now offers explicit **Delete / Bypass / Keep**, and `save_td_project` requires **Overwrite / Keep** consent before replacing an existing Save As target. Timeout, close, UI loss, disconnect and duplicate consumption all fail closed to Keep; explicit YOLO remains separately reported and missing UI is never approval. - Added structured `get_editor_context`, `pulse_td_parameter`, `edit_td_node_metadata`, and Save/Save As bridge routes that work with `TDMCP_BRIDGE_ALLOW_EXEC=0`; extended `create_td_node` with legacy-preserving auto/explicit placement and viewer state. - **Build-aware Agent Enablement & Runtime Readiness Wave 2** — added bounded local-first `get_td_docs`, manifest-owned `manage_agent_skills`, dry-run-first `tdmcp skills`, deterministic local Codex/Claude skill bundles, and redacted `tdmcp status`. Added the authenticated, content-free `GET /api/interactions/status` readiness route; all new structured bridge reads remain independent of `TDMCP_BRIDGE_ALLOW_EXEC`. - **Project-scoped Ownership & Reversible Setup Wave 3** — added explicit user/project package storage, native Claude Code and Cursor project/user client-registration targets, Codex user registration, dry-run/check/redacted-diff/owned-entry removal, atomic verified writes with concurrent-change and symlink guards, and project-aware `tdmcp status` observations. Bare `tdmcp doctor` now diagnoses the environment while package diagnostics move to `tdmcp packages doctor`; known legacy package-doctor calls remain temporarily compatible with a deprecation warning. Codex project scope fails closed because no supported native target was verified. - **Grounded, Verified & Calibrated Local Copilot Wave 4** — local copilot turns now receive one ephemeral, bounded editor-context read; can invoke canonical registered prompts through a schema-validated local adapter; verify supported mutations with bounded read-only evidence before reporting completion; and spend at most one read-only recovery action without retrying ambiguous mutations, authorization failures, panic, blackout or other emergency commands. Menu-value recovery uses a bounded authenticated structured read that remains available with bridge exec disabled. Added sandbox-only `tdmcp copilot-calibrate`, exact model-build cache identity, and compatibility-preserving `recommend` / fail-closed `enforce` tier policy across ask, headless/browser chat and Telegram. TouchDesigner-live grounding and mutation verification remain unverified pending a safe bridge. Wave 13 later passed exact synthetic real-model calibration, including native vision capability and image input; the separate bounded visual-critique rubric/TD fixture gate remains FAIL/UNVERIFIED and does not authorize mutation. - **Project-Owned Context & Auditable Copilot Turns Wave 5** — added the optimistic, atomic `manage_project_brief` tool and explicit `tdmcp://project/brief` resource for a bounded `/.tdmcp/agent-brief.json`; the built-in copilot injects that brief once per turn as ephemeral untrusted evidence and never persists it in chat history. Added one exactly-once, allowlist-only receipt across ask, browser/headless chat and Telegram terminal paths, with compact adapter output and the bounded `tdmcp://session/receipts{?limit,status}` resource. Receipt persistence is opt-in, private and retention-bounded; perform mode, emergency tools and per-turn `noPersist` skip writes. Neither feature records raw tool payloads, transcripts, images, RAG excerpts or secrets, expands a tool tier, or requires bridge exec. Live project-root inference and live mutation evidence remain unverified until the bridge/model endpoints are available. - **Bounded Live Project Discovery Wave 6** — promoted `find_td_nodes` to an authenticated compact bridge-side search while keeping its legacy structured fallback, and added `find_td_parameters` with bounded node/parameter/time budgets, stable ordering, point-in-time value/expression/ mode/non-default filters, secret redaction, anti-oracle behavior, and skip-forward counters for unreadable parameters. Both routes work with `TDMCP_BRIDGE_ALLOW_EXEC=0`; live QA passed on TD 099 build 2025.32820. A live undo probe proved ordinary nested undo/redo but found that `annotateCOMP` closes/replaces an outer block, so whole-tool undo remains intentionally held while the existing per-mutating-request wrapper is preserved. Wave 8 later also holds automated one-item undo after proving that repeated native string labels do not provide a safe action identity. - **Action-aware, Transactional Editor Workflows Wave 7** — extended existing surfaces without adding duplicate tools: - `focus_network_editor` now accepts action/framing/enabled policy, requires a same-parent target group, reuses an active/already-owning compatible pane, replaces stale selection, assigns current, performs bounded generation-aware follow and returns typed suppression in Perform/UI-unavailable states. Core pane/selection/framing behavior passed live on TD 099 build 2025.32820; actual headless TD, other builds and unusual pane layouts remain **UNVERIFIED**, and transient colour highlight remains **HELD**. - Added `insert_operator_at_selection`, a narrow Layer 2 editor primitive that compare-and-swaps the exact active owner/current/single selection, creates one live-allowlisted same-family operator, places it explicitly without overlap, rewires one deterministic downstream edge while preserving siblings, and returns bounded topology/idempotency/rollback receipts. Wave 8's fresh main-thread-only authenticated route passed connector, placement, replay, conflict, rollback and one-item undo/redo on 2025.32820 without reproducing the earlier probe-driver thread conflict. - `manage_component` save and `make_portable_tox` now share one authenticated, idempotent TOX export job: refuse overwrite by default, optionally request exact **Overwrite / Keep** consent, save to a same-directory temporary, verify and atomically promote it, restore portable DAT/`externaltox` state in `finally`, and expose bounded polling/cancellation receipts. `as_is`, `portable` and induced restoration failure passed a service-level live probe on 2025.32820. The legacy component-load path is unchanged and remains exec-gated; filesystem artifacts are not TouchDesigner undo. - `manage_packages action:"reconcile"` adds dry-run-first marker ownership, stable expiring plans and **Delete / Bypass / Keep** apply. Local staged content is quarantined before registry commit and restored on failure; a legacy uninstall with a live target now returns a safe plan instead of deleting local state first. Wave 8 passed the authenticated Keep, Bypass/Delete, explicit YOLO, stale-plan, quarantine/registry, undo/redo and cleanup matrix against disposable TD and local storage. - `add_custom_parameters` moved add off raw Python to the structured bridge and preserves legacy `{ comp_path, page, params }` while adding transactional edit/delete/sort/page lifecycle operations, rich live-proven styles, EXPRESSION/BIND, built-in protection, exact rollback and bounded idempotency. Old warning-only partial add is now all-or-rollback; exact matches are `unchanged` and conflicts are not replaced. Wave 8 passed the authenticated final route for lifecycle, exact undo/redo, replay/conflict, induced rollback and rollback undo safety on 2025.32820; parameter **EXPORT mode is HELD**. - A real multi-request live probe confirmed whole-MCP native undo as **FAIL / HELD**: TD terminates a dangling block when a Web Server DAT callback returns, so later requests cannot join it. One named block per mutating REST request remains the default. - The reported macOS external-plugin alert was diagnosed as a local trust **FAIL**, not a bridge failure: this TouchDesigner bundle has an invalid code seal and FreenectTOP is ad-hoc signed/Gatekeeper-rejected. Plugin registration and cooking remain **UNVERIFIED**; no security settings or install state were changed. - **External-integration Wave 1** — five new artist-facing bridge/scaffold tools: - **`create_raytk_sdf_graph`** (Layer 1, CLI `raytk-sdf-graph`) builds a deeper RayTK SDF graph with optional secondary SDF, `simpleUnion`, `basicMat`, `lookAtCamera`, `pointLight`, `raymarchRender3D`, and native output TOP. - **`create_iphone_depth_source`** (Layer 1, CLI `iphone-depth-source`) scaffolds TDLidar/Record3D/generic NDI+OSC iPhone depth inputs with color, depth, sensor, setup-hint, and point-cloud placeholder outputs. - **`create_sam2_segmentation_bridge`** (Layer 1, CLI `sam2-segmentation-bridge`) builds a TouchDesigner bridge surface for external SAM2/FastSAM masks via ComfyUI, WebSocket, NDI, Syphon/Spout, or file-watch transports. - **`connect_companion_surface`** (Layer 2, CLI `companion-osc-surface`) creates an OSC Companion/Stream Deck button surface with mapping DATs, target parameter binding, and optional feedback channels. - **`connect_obs_recorder`** (Layer 2, CLI `obs-recorder`) creates OBS websocket v5 request templates, status/setup DATs, and optional NDI or Syphon/Spout capture publishing while redacting the OBS password from returned reports. - **External-integration Wave 2** — six additional runtime-gated scaffolds for computer vision, body tracking, mobile OSC, voice prompting, and engine hosts: - **`create_yolo_onnx_tracker`** (Layer 1, CLI `yolo-onnx-tracker`) creates a YOLO/ONNX detection bridge with external WebSocket, ONNX Script CHOP, NDI, and file-watch modes plus stable `detections`, `tracks_out`, and `annotated_out` outputs. - **`create_nuitrack_body_bus`** (Layer 1, CLI `nuitrack-body-bus`) scaffolds a Nuitrack skeleton channel bus over OSC, WebSocket, TCP JSON, or sample data. - **`create_orbbec_depth_silhouette`** (Layer 1, CLI `orbbec-depth-silhouette`) builds an Orbbec/Kinect-compatible depth silhouette chain with synthetic/file fallback modes and explicit SDK/hardware warnings. - **`create_touchosc_layout`** (Layer 2, CLI `touchosc-layout`) creates a TouchOSC-oriented OSC mapping surface and JSON layout manifest without claiming proprietary `.tosc` document generation. - **`create_voice_prompt_pipeline`** (Layer 2, CLI `voice-prompt-pipeline`) creates a dry-run/approval-gated voice-to-prompt scaffold aligned with the AI Party policy boundary. - **`connect_touchengine_notch`** (Layer 2, CLI `touchengine-notch`) creates a TouchEngine/Notch host scaffold with NDI/Syphon fallback modes, stable output TOP, control channels, and licensing/runtime warnings. - **External-integration Wave 3** — six VJ/show-pipeline scaffolds for external control surfaces and engine handoffs: - **`connect_resolume_arena`** (Layer 2, CLI `resolume-arena`) creates a Resolume Arena/Avenue OSC command/status scaffold with layer, deck, clip, and preview handoff metadata. - **`connect_madmapper_surface`** (Layer 2, CLI `madmapper-surface`) creates a MadMapper OSC surface/media map plus Syphon/Spout/NDI handoff notes. - **`create_mocap_stream_bridge`** (Layer 2, CLI `mocap-stream-bridge`) creates an OptiTrack/Rokoko/Axis Studio/VRPN-style skeleton and rigid-body mapping bus. - **`create_blender_scene_bridge`** (Layer 2, CLI `blender-scene-bridge`) creates a Blender scene handoff scaffold for file-watch, OSC, or WebSocket metadata workflows without claiming to launch Blender. - **`create_unreal_livelink_bridge`** (Layer 2, CLI `unreal-livelink-bridge`) creates an Unreal Live Link/OSC/NDI handoff scaffold with subject maps and event queue metadata. - **`create_vcv_rack_bridge`** (Layer 2, CLI `vcv-rack-bridge`) creates a VCV Rack OSC/MIDI/CV modulation map with explicit live-Rack validation warnings. - **External-integration Wave 4** — six show-control and broadcast/playout scaffolds for runtime-gated venue workflows: - **`connect_qlab_cue_stack`** (Layer 2, CLI `qlab-cue-stack`) creates a QLab OSC cue-stack command/status surface with transport rows and rehearsal notes. - **`connect_lighting_console_osc`** (Layer 2, CLI `lighting-console-osc`) creates a safety-gated OSC command surface for grandMA3, ETC Eos, ChamSys, Avolites, or generic OSC lighting consoles without sending direct DMX. - **`connect_max_msp_bridge`** (Layer 2, CLI `max-msp-bridge`) creates a Max/MSP OSC bridge scaffold with parameter and audio-feature channel maps. - **`create_openxr_controller_bridge`** (Layer 2, CLI `openxr-controller-bridge`) creates an OpenXR/SteamVR controller pose and button bus for external OSC/WebSocket/manual adapters. - **`connect_vmix_production`** (Layer 2, CLI `vmix-production`) creates a vMix HTTP/API command-template scaffold for input switching, overlays, recording, and streaming. - **`connect_casparcg_server`** (Layer 2, CLI `casparcg-server`) creates a CasparCG AMCP/playout scaffold with channel/layer command maps and media manifest notes. - **External-integration Wave 5** — six creative-app, DAW, NDI, and browser-input scaffolds: - **`connect_millumin_show`** (Layer 2, CLI `millumin-show`) creates a Millumin OSC layer/column/dashboard command surface. - **`connect_isadora_patch`** (Layer 2, CLI `isadora-patch`) creates an Isadora OSC actor, watcher, and scene exchange scaffold. - **`connect_unity_osc_bridge`** (Layer 2, CLI `unity-osc-bridge`) creates a Unity OSC object/event bridge with NDI/Syphon preview handoff notes. - **`connect_reaper_transport`** (Layer 2, CLI `reaper-transport`) creates a REAPER OSC transport, marker, and track-control scaffold. - **`create_ndi_router_matrix`** (Layer 2, CLI `ndi-router-matrix`) creates an NDI source/output routing matrix contract without claiming live NDI discovery. - **`connect_webrtc_browser_input`** (Layer 2, CLI `webrtc-browser-input`) creates a browser/WebRTC media/data-channel handoff scaffold for external signaling apps. - **External-integration Wave 6** — six runtime I/O, switcher, IoT, and sensor scaffolds: - **`connect_spout_syphon_router`** (Layer 2, CLI `spout-syphon-router`) creates a Syphon/Spout texture-sharing ingress/egress router with route maps and platform-gated setup notes. - **`connect_blackmagic_atem`** (Layer 2, CLI `blackmagic-atem`) creates a Blackmagic ATEM command-map scaffold with UDP transport placeholders, input rows, macro rows, and operator-approval warnings. - **`connect_oscquery_namespace`** (Layer 2, CLI `oscquery-namespace`) creates an OSCQuery HTTP namespace fetcher plus OSC send/receive action maps. - **`connect_mqtt_iot_bus`** (Layer 2, CLI `mqtt-iot-bus`) creates an MQTT Client DAT bus scaffold for IoT sensors, installation telemetry, and policy-gated operator command topics. - **`create_depthai_oak_pipeline`** (Layer 2, CLI `depthai-oak-pipeline`) creates a DepthAI/OAK camera scaffold with OAK Device and OAK Select TOP/CHOP placeholders. - **`connect_arkit_face_capture`** (Layer 2, CLI `arkit-face-capture`) creates an ARKit Face Capture OSC scaffold with blendshape and head-transform maps. - **External-integration Wave 7** — six performance-hardware and show-protocol scaffolds: - **`connect_pangolin_beyond`** (Layer 2, CLI `pangolin-beyond`) creates a safety-gated Pangolin Beyond laser-control scaffold with zone, cue, blackout, and operator-approval maps. - **`create_hokuyo_lidar_bus`** (Layer 2, CLI `hokuyo-lidar-bus`) creates a Hokuyo LiDAR scanner bus with scan-zone maps and live-calibration notes. - **`connect_supercollider_synth`** (Layer 2, CLI `supercollider-synth`) creates a SuperCollider OSC synth/bus scaffold without evaluating SuperCollider code. - **`connect_ableton_link_session`** (Layer 2, CLI `ableton-link-session`) creates an Ableton Link beat/bar/session timing scaffold for tempo-locked visuals. - **`create_decklink_io_router`** (Layer 2, CLI `decklink-io-router`) creates a Blackmagic DeckLink video-device input/output router scaffold. - **`connect_midi_mpe_controller`** (Layer 2, CLI `midi-mpe-controller`) creates a MIDI MPE expressive-controller scaffold with zone and expression maps. - **External-integration Wave 8** — six live-coding, VJ/media-server, and specialized tracking scaffolds: - **`connect_tidalcycles_livecoding`** (Layer 2, CLI `tidalcycles-livecoding`) creates a TidalCycles/SuperDirt OSC pattern and orbit bridge scaffold. - **`connect_vdmx_workspace`** (Layer 2, CLI `vdmx-workspace`) creates a VDMX OSC/Syphon workspace scaffold with layer, clip, and preview maps. - **`connect_disguise_stage`** (Layer 2, CLI `disguise-stage`) creates a disguise/d3 HTTP and OSC show-control scaffold for timelines and layers. - **`create_azure_kinect_body_bus`** (Layer 2, CLI `azure-kinect-body-bus`) creates an Azure Kinect body/depth source scaffold. - **`create_zed_depth_bus`** (Layer 2, CLI `zed-depth-bus`) creates a ZED camera depth, body, and point-cloud source scaffold. - **`create_leap_motion_hand_bus`** (Layer 2, CLI `leap-motion-hand-bus`) creates a Leap Motion hand and gesture source scaffold. - **External-integration Wave 9** — six tracking, touch-surface, and timecode infrastructure scaffolds: - **`create_blacktrax_tracking_bus`** (Layer 2, CLI `blacktrax-tracking-bus`) creates a BlackTrax tracking bus with trackable, zone, and calibration maps. - **`create_ncam_camera_tracking_bus`** (Layer 2, CLI `ncam-camera-tracking-bus`) creates an NCAM camera-tracking bus with camera and lens-profile maps. - **`create_ouster_lidar_bus`** (Layer 2, CLI `ouster-lidar-bus`) creates an Ouster LiDAR bus with range selection, zone maps, and sensor setup notes. - **`connect_tuio_touch_surface`** (Layer 2, CLI `tuio-touch-surface`) creates a TUIO touch-surface ingress scaffold with cursor and surface maps. - **`create_multitouch_panel_bus`** (Layer 2, CLI `multitouch-panel-bus`) creates a Windows Multi Touch In DAT scaffold with panel and touch-slot maps. - **`create_ltc_timecode_bridge`** (Layer 2, CLI `ltc-timecode-bridge`) creates an LTC receive/generate bridge with cue maps and audio-routing notes. - **External-integration Wave 10** — six network/protocol ingest scaffolds: - **`create_optitrack_tracking_bus`** (Layer 2, CLI `optitrack-tracking-bus`) creates an OptiTrack/NatNet tracking scaffold with rigid-body and marker maps. - **`connect_video_stream_receiver`** (Layer 2, CLI `video-stream-receiver`) creates a Video Stream In TOP scaffold for RTSP, HLS, SRT, or WebRTC ingest. - **`connect_websocket_control_bus`** (Layer 2, CLI `websocket-control-bus`) creates a WebSocket DAT control scaffold with command and schema maps. - **`connect_serial_device_bus`** (Layer 2, CLI `serial-device-bus`) creates a Serial DAT/CHOP scaffold for microcontrollers, sensors, and device telemetry. - **`connect_udp_telemetry_bridge`** (Layer 2, CLI `udp-telemetry-bridge`) creates a UDP In/Out DAT telemetry scaffold with packet and reply maps. - **`create_artnet_discovery_panel`** (Layer 2, CLI `artnet-discovery-panel`) creates an Art-Net DAT discovery scaffold with optional DMX In monitor maps. - **External-integration Wave 11** — six projection/display infrastructure scaffolds: - **`create_mpcdi_projection_mapper`** (Layer 2, CLI `mpcdi-projection-mapper`) creates an MPCDI TOP/DAT calibration scaffold with projector and region maps. - **`create_vioso_warp_panel`** (Layer 2, CLI `vioso-warp-panel`) creates a VIOSO TOP projection-warp scaffold with projector and blend-zone maps. - **`create_direct_display_output`** (Layer 2, CLI `direct-display-output`) creates a Direct Display Out TOP scaffold with monitor inventory and output maps. - **`create_scalable_display_bus`** (Layer 2, CLI `scalable-display-bus`) creates a Scalable Display TOP scaffold with tile maps and canvas metadata. - **`create_window_output_matrix`** (Layer 2, CLI `window-output-matrix`) creates a Window COMP output-matrix scaffold with window and source maps. - **`create_monitor_layout_panel`** (Layer 2, CLI `monitor-layout-panel`) creates a Monitors DAT preflight scaffold with monitor, GPU, and checklist maps. - **External-integration Wave 12** — six spatial/industrial data bridge scaffolds: - **`create_realsense_depth_bus`** (Layer 2, CLI `realsense-depth-bus`) creates a RealSense depth-camera scaffold with RealSense TOP, NDI, WebSocket adapter, and sample-source modes. - **`create_livox_lidar_bus`** (Layer 2, CLI `livox-lidar-bus`) creates a Livox LiDAR adapter scaffold with point-stream schemas, zone maps, and calibration notes. - **`connect_xsens_mvn_mocap`** (Layer 2, CLI `xsens-mvn-mocap`) creates an Xsens MVN mocap scaffold with actor/segment maps and coordinate-space notes. - **`connect_houdini_engine_bridge`** (Layer 2, CLI `houdini-engine-bridge`) creates a Houdini Engine/HDA/cache handoff scaffold with parameter maps. - **`connect_omniverse_usd_bridge`** (Layer 2, CLI `omniverse-usd-bridge`) creates an Omniverse/USD stage scaffold with layer and variant maps. - **`connect_opcua_industrial_bus`** (Layer 2, CLI `opcua-industrial-bus`) creates an OPC UA telemetry scaffold with node maps and read-only safety notes. - **External-integration Wave 13** — six creative AI inference bridge scaffolds: - **`connect_replicate_prediction_bridge`** (Layer 2, CLI `replicate-prediction-bridge`) creates a Replicate-style prediction handoff scaffold with request templates, webhook/polling maps, and output contracts. - **`connect_a1111_webui_bridge`** (Layer 2, CLI `a1111-webui-bridge`) creates an AUTOMATIC1111/Forge WebUI scaffold with prompt slots and result maps. - **`connect_huggingface_inference_bridge`** (Layer 2, CLI `huggingface-inference-bridge`) creates a Hugging Face inference scaffold with task input maps and token-env hints. - **`connect_whisper_transcription_bus`** (Layer 2, CLI `whisper-transcription-bus`) creates a Whisper-compatible transcription bus with audio/chunk ingest and segment maps. - **`connect_rvc_voice_conversion_bus`** (Layer 2, CLI `rvc-voice-conversion-bus`) creates an RVC voice-conversion scaffold with source audio, model maps, and consent/latency notes. - **`connect_runway_video_bridge`** (Layer 2, CLI `runway-video-bridge`) creates a Runway-style video generation scaffold with prompt, request, and result maps. - **External-integration Wave 14** — six observability/data-ops bridge scaffolds: - **`connect_kafka_event_bus`** (Layer 2, CLI `kafka-event-bus`) creates a Kafka/Redpanda event-bus scaffold with topic maps and schema hints. - **`connect_redis_pubsub_bus`** (Layer 2, CLI `redis-pubsub-bus`) creates a Redis Pub/Sub/Streams scaffold with channel maps and keyspace safety notes. - **`connect_influxdb_timeseries_bridge`** (Layer 2, CLI `influxdb-timeseries-bridge`) creates an InfluxDB telemetry scaffold with measurement and field maps. - **`connect_prometheus_metrics_panel`** (Layer 2, CLI `prometheus-metrics-panel`) creates a Prometheus metrics scaffold with metric maps and alert routes. - **`connect_grafana_annotation_bridge`** (Layer 2, CLI `grafana-annotation-bridge`) creates a Grafana annotation/event-marker scaffold with dashboard, panel, and tag maps. - **`connect_homeassistant_state_bus`** (Layer 2, CLI `homeassistant-state-bus`) creates a Home Assistant state/service scaffold with entity maps, service maps, and physical-action safety notes. - **External-integration Wave 15** — six content-ops and collaboration bridge scaffolds: - **`connect_google_sheets_cue_table`** (Layer 2, CLI `google-sheets-cue-table`) creates a Google Sheets cue-table scaffold with cue rows, column validation, and adapter/writeback safety notes. - **`connect_airtable_content_bus`** (Layer 2, CLI `airtable-content-bus`) creates an Airtable content scaffold with record maps, field maps, and sync-policy notes. - **`connect_notion_show_rundown`** (Layer 2, CLI `notion-show-rundown`) creates a Notion editorial rundown scaffold with scene maps, property maps, and approval policy. - **`connect_figma_design_tokens`** (Layer 2, CLI `figma-design-tokens`) creates a Figma token scaffold with token rows, component-review rows, and style metadata. - **`connect_slack_ops_bridge`** (Layer 2, CLI `slack-ops-bridge`) creates a Slack operator-alert scaffold with alert rows and approval-gated command rows. - **`connect_s3_media_bucket`** (Layer 2, CLI `s3-media-bucket`) creates an S3-compatible media manifest scaffold with asset rows, cache policy, and credential/signing safety notes. - **External-integration Wave 16** — six venue/public-ops bridge scaffolds: - **`connect_calendar_schedule_bus`** (Layer 2, CLI `calendar-schedule-bus`) creates a calendar/ICS schedule scaffold with event rows, reminder maps, and blackout-window policy. - **`connect_ticketing_checkin_bus`** (Layer 2, CLI `ticketing-checkin-bus`) creates a ticketing/check-in scaffold with aggregate gate counts, ticket-tier maps, and PII/token safety notes. - **`connect_pos_sales_telemetry`** (Layer 2, CLI `pos-sales-telemetry`) creates a POS aggregate telemetry scaffold with sales metrics, revenue buckets, and PCI/PII safety notes. - **`connect_weather_forecast_bus`** (Layer 2, CLI `weather-forecast-bus`) creates a weather forecast/station scaffold with forecast rows, sensor maps, and alert maps. - **`connect_gtfs_transit_feed`** (Layer 2, CLI `gtfs-transit-feed`) creates a GTFS static/realtime transit scaffold with route maps, stop maps, and arrival predictions. - **`connect_parking_occupancy_bus`** (Layer 2, CLI `parking-occupancy-bus`) creates a parking occupancy scaffold with zone occupancy rows, sensor maps, and signage policy. - **External-integration Wave 17** — six geospatial and mobility feed scaffolds: - **`connect_map_tile_overlay`** (Layer 2, CLI `map-tile-overlay`) creates a map tile overlay scaffold with tile layer maps, viewport metadata, and attribution rows. - **`connect_geojson_feature_bus`** (Layer 2, CLI `geojson-feature-bus`) creates a GeoJSON feature scaffold with feature rows, property maps, and style rules. - **`connect_gps_fleet_tracker`** (Layer 2, CLI `gps-fleet-tracker`) creates a GPS/fleet tracking scaffold with sanitized asset positions and geofence maps. - **`connect_adsb_aircraft_bus`** (Layer 2, CLI `adsb-aircraft-bus`) creates an ADS-B aircraft scaffold with aircraft rows, altitude bands, and track-history metadata. - **`connect_ais_vessel_bus`** (Layer 2, CLI `ais-vessel-bus`) creates an AIS vessel scaffold with vessel rows, waterway zones, and route hints. - **`connect_public_alerts_bus`** (Layer 2, CLI `public-alerts-bus`) creates a public-alert scaffold with advisory alert rows, severity maps, and routing policy. - **External-integration Wave 18** — six audience/social interaction feed scaffolds: - **`connect_twitch_eventsub_bus`** (Layer 2, CLI `twitch-eventsub-bus`) creates a Twitch EventSub/chat scaffold with sanitized event rows, reward maps, and moderation policy. - **`connect_youtube_live_chat_bus`** (Layer 2, CLI `youtube-live-chat-bus`) creates a YouTube Live Chat scaffold with message rows, super-chat tiers, and moderation policy. - **`connect_discord_interaction_bus`** (Layer 2, CLI `discord-interaction-bus`) creates a Discord gateway/webhook scaffold with command maps, message maps, and interaction approval policy. - **`connect_tiktok_live_events_bus`** (Layer 2, CLI `tiktok-live-events-bus`) creates a TikTok Live event scaffold with event rows, gift tiers, and moderation policy. - **`connect_matrix_room_bus`** (Layer 2, CLI `matrix-room-bus`) creates a Matrix room event scaffold with room-event rows, reaction maps, and approval policy. - **`connect_rss_feed_bus`** (Layer 2, CLI `rss-feed-bus`) creates an RSS/Atom feed scaffold with item rows, categories, and refresh policy. - **External-integration Wave 19** — six onsite proximity and visitor-input scaffolds: - **`connect_rfid_badge_bus`** (Layer 2, CLI `rfid-badge-bus`) creates an RFID badge-reader scaffold with sanitized badge-event rows, reader maps, and privacy policy. - **`connect_nfc_tap_bus`** (Layer 2, CLI `nfc-tap-bus`) creates an NFC tap scaffold with tap-event rows, station maps, and consent policy. - **`connect_ble_beacon_bus`** (Layer 2, CLI `ble-beacon-bus`) creates a BLE beacon proximity scaffold with beacon rows, zone maps, and smoothing policy. - **`connect_uwb_anchor_bus`** (Layer 2, CLI `uwb-anchor-bus`) creates a UWB anchor/tag scaffold with anchor rows, tag-position rows, and spatial policy. - **`connect_qr_scan_bus`** (Layer 2, CLI `qr-scan-bus`) creates a QR scan scaffold with scan rows, route maps, and sanitization policy. - **`connect_wifi_presence_bus`** (Layer 2, CLI `wifi-presence-bus`) creates a Wi-Fi presence scaffold with aggregate occupancy rows, dwell buckets, and privacy policy. - **RayTK native integration (node-graph, offline-built)** — beyond package-manager staging, tdmcp can now drive RayTK (t3kt/raytk) as editable ROP node graphs, complementary to (never replacing) the GLSL `create_raymarch_scene`/`create_sdf_field`: - **`create_raytk_op`** (Layer 3) — instances one RayTK ROP master by op-name (e.g. `sphereSdf`, `raymarchRender3D`, `lookAtCamera`) via the same `COMP.copy(master)` primitive RayTK's palette uses, resolving the install-dependent master path **live** (RayTK's `pathsByOpType` lookup → category-folder search, never hardcoded) and optionally wiring a typed input. CLI: `tdmcp-agent raytk-op`. - **`create_raytk_scene`** (Layer 1) — builds the minimal renderable RayTK chain (`sphereSdf → raymarchRender3D → Null TOP`, renderer inputs 1=scene/2=camera/3=light, built-in camera+light by default) with optional second SDF (`simpleUnion`), inline `basicMat`, explicit `lookAtCamera`/`pointLight`. Fails forward with "stage & load RayTK first" guidance and warns that the async shader compile may leave the first preview black. CLI: `tdmcp-agent raytk-scene`. - **`tdmcp://raytk/operators`** (+ `tdmcp://raytk/operators/{category}`) MCP resource — a committed RayTK operator catalog (18 categories, verified op masters, typed Sdf/float/vec4/Ray/Light connectors, the TD version gate, the minimal chain) so the AI picks the right ROP before instancing. - **Package version-gate honesty** — the `raytk` manifest's stale `tdVersionRange` (`2022+`) is corrected to `2025.30770+` with a `versionGate` (RayTK 0.46 needs the TD 2025.30770 experimental build; pin ≤0.45 on 2023.x); `manage_packages doctor raytk` now detects the live TD build and warns when it predates the gate. - Live-validated on TouchDesigner build **2025.32820** with RayTK **0.46** loaded: all six ROP masters resolve via `pathsByOpType`, copy, and wire; the raymarch shader compiles and the output TOP renders a real (non-black) `sphereSdf ∪ boxSdf` + `basicMat` scene. `create_raytk_op` connects an existing op into a new op's input. Wiring uses connector-to-connector (`dst.inputConnectors[i].connect(src.outputConnectors[0])`) — RayTK COMP connectors reject `.connect(op)`. ### Changed - Release availability banners and `tdmcp show` help now identify the packaged v0.13.2 feature set from package metadata instead of continuing to label those capabilities as source-only after publication. - Workspace `restore` and `cancel` now perform exactly one same-key replay after an ambiguous initial connection/timeout loss, matching the existing `open` recovery boundary. Deterministic 4xx authorization/input failures are not retried, and a second ambiguous loss stops without starting a new transition. - Corrected `delete_td_node` undo documentation: the final mutation is covered by the existing per-REST `ui.undo` wrapper. Whole-MCP-tool undo and explicit undo/redo remain **UNVERIFIED — pending bridge** and are not enabled by default. - Existing `{ path, mode }` delete calls remain valid, but `mode: "delete"` now waits for native consent and safely returns Keep when no decision is available; `mode: "bypass"` remains immediate and reversible. ### Fixed - Refreshed the locked production dependency graph to patched `fast-uri`, `hono`, and `ip-address` releases, closing the host-confusion, request-DoS, cross-request disclosure, and SSRF/trust-boundary advisories reported by `npm audit --omit=dev`. Development-only vulnerable transitive packages were refreshed in the same lockfile pass; the resulting full audit is clean. - Restricted raw-off sessions now reject caller-supplied code at both the MCP and bridge boundaries, including recipe parameter expressions, `python_code`, `glsl_code`, direct/imported GLSL and Shader Park sources, DAT text/vault writes, custom-parameter expression/bind assignments, rebuild specs, direct CLI implementation calls, and parameter expression/bind modes. Generic create/update/batch/editor routes now preflight executable operator types, DAT source files and callback/expression parameters before any mutation, including for direct bridge HTTP clients. Safe and directory profiles enforce the same caller-code policy. Safe constant/reset/unbind and read-only structured paths remain available without falling back to `/api/exec`; constant-only rebuild specs remain allowed by the MCP policy but retain their existing bridge-exec transport requirement. - Operator knowledge responses now expose the imported snapshot provenance and distinguish `found_in_snapshot` from `not_in_snapshot`. Missing operator records and empty searches explicitly warn that snapshot absence does not prove absence from the current TouchDesigner build, and resource suggestions use URI-ready operator slugs. - **`create_raytk_sdf_graph`** now sets the copied RayTK `raymarchRender3D` renderer to `1280x720` by default, avoiding TouchDesigner Non-Commercial resolution warnings during live QA while keeping the resolution configurable. - Glama/MCP directory score surface: the package metadata now exposes `TDMCP_TOOL_PROFILE` as a configurable full/safe/directory setting so hosted scanners can opt into the compact build/inspect surface without forcing registry installs away from the default `full` runtime; low-scoring tool definitions also gained clearer descriptions and parameter guidance. - Creative RAG Smithsonian adapter: cards whose Open Access record omits `record_link` no longer emit the bare `record_ID` (an `edanmdm-…` identifier) as `sourceUrl`, which failed the probe-live URL gate ("Shape drift … sourceUrl: Invalid URL"). The adapter now validates URL-ness and builds the canonical object page `https://www.si.edu/object/{record_ID}` when `record_link` is absent, keeping `guid` (ARK) as a last-resort fallback, so every card yields a valid absolute URL. - Hardened Glama and hosted-registry introspection with a compact directory tool profile, reachable container HTTP binding, accurate tool metadata, raw-Python macro replay gating, and schema-backed structured recipe-bundle results. - **`get_preview`** no longer implies that a capture was scaled to the requested size. The bridge may return a TOP at its native resolution, but `width` and `height` were described as the captured image dimensions and the caption printed the returned size as if it were the requested result — misleading for artists and agents inspecting an output. Both parameters are now described as requested dimensions, and when the returned size differs the caption reports both (`1080×1920 native; 640×360 requested`) for ordinary, immediate advanced, and deferred-job image captures alike. Deferred jobs now retain their original requested dimensions for accurate collection captions. Bridge capture and scaling behaviour is unchanged. - **`summarize_td_errors`** now distinguishes warnings from errors. The bridge returns both severities in `result.errors`, but the summary counted and described every entry as an error, so a warning-only network appeared to be failing and could send an agent down the wrong repair path. The response keeps the existing `total` field and adds `error_count` and `warning_count`, each grouped representative sample retains its severity, and the descriptions and suggestions use accurate diagnostic terminology. - The `tdmcp://session/receipts` MCP resource now resolves for bare, partial and reordered query reads. Under MCP SDK 1.30 the documented `{?limit,status}` template resolves reliably only when both parameters appear in template order, so valid reads such as the bare URI, `?limit=5`, or a reversed query order could miss the resource handler entirely. The bare resource is now registered explicitly alongside the documented template, with a bounded query fallback for partial or reordered parameters; the shared parser still rejects unknown paths and unknown query keys. ## [0.13.1] - 2026-07-09 ### Added - Tool-integration campaign Waves 1-7: - **`export_render_preset`** (Layer 3, CLI `export-render-preset`) wraps `record_movie` with named delivery presets for HAP, HAP Alpha, ProRes 422/4444, NotchLC, and MP4 review exports. - **`show_preflight_report`** (Layer 3, CLI `show-preflight`) returns a read-only PASS/WARN/FAIL pre-show report across bridge reachability, node errors, topology, performance budget, and display checks. - **`auto_ui_from_params`** (Layer 2, CLI `auto-ui-from-params`) infers primitive node parameters and generates bound custom-parameter controls for quick playable UI scaffolding. - **`create_companion_surface`** (Layer 2, CLI `companion-surface`) composes auto UI, a playable fader/cue surface, and optional preflight diagnostics around an existing node or COMP. - **`clip_audio_transport`** (Layer 2, CLI `clip-transport`) creates a deterministic movie/audio transport container with video/audio outputs and shared Play, Loop, and Speed controls. - **`osc_router_matrix`** (Layer 2, CLI `osc-router`) creates a reusable OSC target/control matrix with one Constant CHOP + OSC Out CHOP lane per external target. - **`qlab_osc_bridge`** (Layer 2, CLI `qlab-osc`) presets QLab transport and cue-start OSC routes. - **`atem_switcher_control`** (Layer 2, CLI `atem-switcher-control`) presets safe atemOSC/Companion switcher routes for cut/auto/FTB plus program/preview input selection without using the Blackmagic SDK directly. - **`resolume_vdmx_output_chain`** (Layer 2, CLI `resolume-vdmx-output`) presets OSC control lanes for Resolume, VDMX, or both. - **`obs_stream_control`** (Layer 2, CLI `obs-stream-control`) creates an OBS WebSocket v5 control rig with stream, recording, and scene-switch request channels without storing OBS passwords. - **`edit_shader_live_loop`** (Layer 3, CLI `shader-live-loop`) edits a GLSL/Text DAT and immediately runs the shader feedback loop: post-edit error inspection plus optional compact inline preview. - **`blender_scene_import`** (Layer 1, CLI `blender-scene-import`) creates a Blender-oriented PBR render scaffold from `.blend`/FBX/OBJ/glTF/GLB/USD assets, with deterministic layout, fallback primitive, material controls, and `.blend` export guidance. - **`marketplace_index_seed`** (Library, CLI `marketplace-index-seed`) writes a guarded starter marketplace seed JSON with built-in pack ideas plus custom entries, without replacing `local_marketplace_index`. - **`one_source_five_ways`** (AI, CLI `one-source-five-ways`) turns one source node/asset into five deterministic remix briefs spanning colorway, motion, texture, spatial reframing, and cueable performance variants. - **`projector_calibration_wizard`** (Layer 1, CLI `projector-calibration`) scaffolds generated-grid/source TOP calibration lanes with crop, corner-pin, level, preview, and controls while keeping physical projector alignment marked live-unverified. - **`notch_touchengine_bridge`** (Layer 2, CLI `notch-touchengine-bridge`) scaffolds a guarded Notch TOP or Engine COMP/TouchEngine bridge with notes and output wiring while keeping license/runtime validation explicit. - **`lidar_floor_tracker`** (Layer 1, CLI `lidar-floor-tracker`) scaffolds a synthetic/Ouster/Leuze/UDP floor-tracking CHOP pipeline with preview output, keeping real sensor validation marked hardware-unverified. - **`raytk_expr_graph_builder`** (Layer 1, CLI `raytk-expr-graph`) builds a preset or explicit RayTK ROP expression graph from copied RayTK masters, typed connector edges, simple parameter values, deterministic node layout, and a native `out1` TOP, while keeping live RayTK render/cook validation explicit. - **RayTK native integration (node-graph, offline-built)** — beyond package-manager staging, tdmcp can now drive RayTK (t3kt/raytk) as editable ROP node graphs, complementary to (never replacing) the GLSL `create_raymarch_scene`/`create_sdf_field`: - **`create_raytk_op`** (Layer 3) — instances one RayTK ROP master by op-name (e.g. `sphereSdf`, `raymarchRender3D`, `lookAtCamera`) via the same `COMP.copy(master)` primitive RayTK's palette uses, resolving the install-dependent master path **live** (RayTK's `pathsByOpType` lookup → category-folder search, never hardcoded) and optionally wiring a typed input. CLI: `tdmcp-agent raytk-op`. - **`create_raytk_scene`** (Layer 1) — builds the minimal renderable RayTK chain (`sphereSdf → raymarchRender3D → Null TOP`, renderer inputs 1=scene/2=camera/3=light, built-in camera+light by default) with optional second SDF (`simpleUnion`), inline `basicMat`, explicit `lookAtCamera`/`pointLight`. Fails forward with "stage & load RayTK first" guidance and warns that the async shader compile may leave the first preview black. CLI: `tdmcp-agent raytk-scene`. - **`tdmcp://raytk/operators`** (+ `tdmcp://raytk/operators/{category}`) MCP resource — a committed RayTK operator catalog (18 categories, verified op masters, typed Sdf/float/vec4/Ray/Light connectors, the TD version gate, the minimal chain) so the AI picks the right ROP before instancing. - **Package version-gate honesty** — the `raytk` manifest's stale `tdVersionRange` (`2022+`) is corrected to `2025.30770+` with a `versionGate` (RayTK 0.46 needs the TD 2025.30770 experimental build; pin ≤0.45 on 2023.x); `manage_packages doctor raytk` now detects the live TD build and warns when it predates the gate. - Live-validated on TouchDesigner build **2025.32820** with RayTK **0.46** loaded: all six ROP masters resolve via `pathsByOpType`, copy, and wire; the raymarch shader compiles and the output TOP renders a real (non-black) `sphereSdf ∪ boxSdf` + `basicMat` scene. `create_raytk_op` connects an existing op into a new op's input. Wiring uses connector-to-connector (`dst.inputConnectors[i].connect(src.outputConnectors[0])`) — RayTK COMP connectors reject `.connect(op)`. ### Changed - Docs follow-through for the tool-integration campaign: public tool-count copy now matches the generated 375-tool reference; EN/PT prompt cookbook entries cover the new integration, RayTK expression-graph, show-readiness, external-control, projector/LiDAR, Blender/Notch and render-handoff flows without adding decorative media; `docs/reference/cli.md` lists the new `tdmcp-agent` campaign subcommands. ### Fixed - Glama/MCP directory score surface: the package metadata now exposes `TDMCP_TOOL_PROFILE` as a configurable full/safe/directory setting so hosted scanners can opt into the compact build/inspect surface without forcing registry installs away from the default `full` runtime; low-scoring tool definitions also gained clearer descriptions and parameter guidance. - Creative RAG Smithsonian adapter: cards whose Open Access record omits `record_link` no longer emit the bare `record_ID` (an `edanmdm-…` identifier) as `sourceUrl`, which failed the probe-live URL gate ("Shape drift … sourceUrl: Invalid URL"). The adapter now validates URL-ness and builds the canonical object page `https://www.si.edu/object/{record_ID}` when `record_link` is absent, keeping `guid` (ARK) as a last-resort fallback, so every card yields a valid absolute URL. ## [0.13.0] - 2026-07-07 ### Added - Consolidation-gate docs & recipes pass (roadmap G1/G2/G3/G5): - **G3 — 10 new orchestrator recipe twins** (`color_grade_basic`, `transition_dissolve`, `text_overlay_lower_third`, `layer_stack_blend`, `strobe_flash`, `test_pattern_grid`, `datamosh_feedback_echo`, `chrome_blobs`, `displacement_warp_noise`, `luma_keyer`) — `validate:recipes` 50/50 → **60/60**, `lint:recipes` clean, and all 10 **live-cook-validated on TD 099 build 2025.32820** (0 node errors / 0 warnings each; the `displacement_warp_noise` displaceTOP weight token was corrected `uvweightx/y` → `uvweight` against the live op). - **G5 — docs completeness.** All 20 new #128 tools now have EN **and** PT prompt-cookbook entries (20/20 each, parity holds); `docs/reference/cli.md` documents the new `tdmcp-agent` subcommands (`bundle-deps`, `export-external-tree`, `narrate-set`, `check-optypes`, `preview --inline [--watch]`, `doctor --json`) and the vault/MCP-tool parity. - CLI parity: 44 previously MCP-only tools are now `tdmcp-agent` subcommands (all 21 vault tools, `get_preview`, `watch_node`, `manage_packages`, `swap_operator`, `copilot_vision`, `auto_repair_loop`, `create_glsl_material`, `publish_recipe_bundle`, and more), plus a parity regression test (`tests/unit/cliToolParity.test.ts`) that keeps every tool Impl wired to the CLI. - `tdmcp-agent doctor --json` is now accepted as an alias for `doctor --output json`. - CI: the Python bridge test job pins `actions/setup-python`, and the `.mcpb` bundle is uploaded as a PR artifact. - `TouchDesignerClient.getHealth()`: typed, Zod-validated client method for the bridge's `GET /api/health` liveness/heartbeat report. ### Fixed - Recipes `glitch_post` and `slime_simulation` bound and set a nonexistent displaceTOP token (`uvweightx`/`uvweighty`), so the displacement silently did nothing. Switched to the real per-axis Displace Weight tokens (`displaceweightx`/`displaceweighty`), verified against the live op; both live-validated in TD 099 build 2025.32820 with 0 node errors / 0 warnings. - `NetworkBuilder.add()` now surfaces the bridge's `parameter_warnings` (params the op could not apply — unknown token or bad value) as build warnings. This was already reported by the bridge and relayed by `create_td_node`, but recipe/Layer 1–2 builds dropped it, so a typo'd parameter name failed silently while the build looked clean. Catches the whole class at build/live-cook time. - Telegram: transport errors no longer embed the bot token in the surfaced error message (`/bot/…` is redacted to `/bot[REDACTED]/…`). - `npm run lint` now checks explicit paths (`src tests scripts`), fixing the 0-files no-op inside linked git worktrees. - Docs: tool count corrected to 355 (generated `docs/reference/tools.md` total) in the README and docs landing pages (EN + PT). - Connectors Directory submission readiness (roadmap gate G6): bundled a Desktop- extension icon (`mcpb/icon.png`, referenced by `manifest.icon`) and enriched the MCPB manifest with `long_description`, `icon`, `repository`, `homepage`, `documentation`, `support`, `license`, `keywords`, `tools_generated`, and `privacy_policies` — all schema-validated by the official `@anthropic-ai/mcpb` packer. A field-by-field submission draft, approval-gate checklist, and migration notes were written under `_workspace/`. ### Changed - G2 coverage gate: ratcheted the `vitest.config.ts` no-regression floors up to the current measured baseline (statements 84→86, branches 70→73, functions 83→85, lines 86→88). The suite-level `Coverage Gate` CI job already enforces these as a required check; the +5pp stretch target (lines ≥ 91, branches ≥ 75) is unchanged. - Roadmap G1 correction: `docs/reference/API_STABILITY.md` (the v1.0 stability pin) already exists and is wired into the docs nav — the roadmap no longer reports it as missing; the only open G1 item is the one-clean-tagged-minor clock. - Release safety: the `release.yml` tag-verify step now also asserts the bootstrap/self-install pins match the release tag, so a tag can never ship one-click install paths that download an older bridge (the pins are held on the last published tag during prep and advanced by `sync-manifest-version.mjs` at release time). - refactor: reduce cognitive complexity of functions flagged by the ratchets — no behavior change. Extracted well-named helpers from five worsened JS/TS functions (`runCli`, `runChat`, `service.sync`, `runAgentTurn`, chat-server `run`), six freshly-added JS/TS functions (`runPreviewInline`, `narrateSetImpl`, `projectFeatures`/`flattenToRings`, `scaffoldVjDeckImpl`, `bundleDependenciesImpl`, `checkOperatorAvailabilityImpl`), and four Python bridge functions (`_route_get_root`, `_route_node_special`, `duplicate`, `poll`). `make complexity` is green again. - Renamed the Desktop-extension build artifacts to match the current `.mcpb` format: `dxt/` → `mcpb/`, `scripts/build-dxt.mjs` → `scripts/build-mcpb.mjs` (log prefix `[build-mcpb]`), `tests/unit/buildDxtScript.test.ts` → `buildMcpbScript.test.ts`; updated `package.json`, `sync-manifest-version.mjs`, and the release workflow. Swept stale `.dxt` format references from the README, install/glossary guides (EN + PT), CLI reference, roadmap, and deployment guide. The `@anthropic-ai/dxt` fallback packer name is retained — it is a real dependency, not a stale format reference. - Privacy policy (EN + PT): corrected the network-activity section to disclose the opt-in, user-initiated outbound calls (`import_shadertoy` → Shadertoy API, `import_isf_shader` → user URL, and the optional local AI copilot) instead of claiming localhost-only egress. The no-telemetry / no-data-collection guarantees are unchanged. ### Fixed - PR #128 review fixes (parameter-watch event path + inline-image + copilot session save): - **`param.changed` now reaches MCP clients by default.** It had been added to the `eventStream` `HIGH_FREQUENCY` drop set, but `transportFactory` builds the default stream without `includeHighFrequency`, so every watched `param.changed` was dropped before it could be forwarded as an MCP logging notification — `watch_parameter_changes` produced zero notifications. `param.changed` is already gated at the source by the watch registry (empty registry ⇒ silent) and coalesced bridge-side, so it is no longer in the blanket drop set; only the genuinely unbounded `timeline.frame`/`node.cook` firehoses stay high-frequency. Live-validated on TD 099 build 2025.32820: a `param.changed` frame now survives the default (non-high-frequency) stream while `node.cook`/`timeline.frame` stay gated. - **Watch-service coalescing no longer loses the resting value.** The poll snapshot advanced *before* the coalesce check dropped the event, so a burst that settled at a new value within the 50 ms window and then stopped (0.1 → 0.2, then quiet) never emitted the final 0.2 — subscribers kept the stale 0.1. The emitted snapshot now advances only on delivery; a coalesced change keeps the old snapshot so the settled value emits on the next post-window poll. Live-validated against real `constantCHOP` parameter values on TD 099. - **Older-bridge watch routes now surface the friendly upgrade message.** Older bridges report an unknown route as HTTP 400 `Unsupported POST /api/params/watch`, not 404; `watchParameters`/`unwatchParameters`/`listParameterWatches` only mapped 404, so a real older bridge surfaced the raw error. They now use the shared `isMissingEndpoint()` helper (matches 404 *and* `Unsupported …`) for all three methods, while a genuine validation 400 still surfaces unchanged. Live-validated: the running bridge returns `400 Unsupported …` for these routes and the client now maps it to reinstall/update guidance. - **`/session/save` returns a structured 422 on a malformed transcript.** `saveCopilotSession` Zod-parses `messages` and can throw; the exception used to bubble to the generic 500 plain-text handler, breaking the JSON contract. The parse/write is now wrapped and returns a `{ ok: false, error }` **422** JSON response, mirroring `/session/load`. - **Inline-image escape sequences no longer contain literal control bytes.** The iTerm2 OSC-1337 and Kitty graphics-protocol strings in `inlineImage.ts` embedded raw ESC/BEL bytes in source; they now use explicit `\x1b`/`\x07` escapes. Runtime output is byte-identical. - **PR #128 review pass 1 (correctness / schema / Python / tests):** - `create_synesthesia_unreal_osc` reported OSC-out errors character-by-character — `OP.errors()` returns a single newline-joined **string**, so `[str(e) for e in _osc.errors()]` iterated its characters. It now splits into lines and takes the first three real messages. Live-validated on TD 099 build 2025.32820: a two-line error string now yields two messages, not `["C","o","n"]`. - `watch_service.unregister` now (1) purges the **removed** par names' stale `_SNAPSHOT`/`_LAST_EMIT` entries on a partial unregister, so a later re-watch of a removed par starts fresh (`_diff_par` sees `_UNSET` and only seeds), and (2) resolves the same **canonical** registry key `register()` stored under even after the op is deleted (alias fallback), so a dead watch is no longer leaked. New `td/tests/test_watch_service.py` regressions cover both; live-validated on TD 099. - `create_interaction_zones` no longer collides two zones whose names sanitize to the same key (e.g. `"left zone"` and `"left/zone"` → `left_zone`) — colliding keys are disambiguated by zone index. Live-checked TD's own silent auto-rename (`left_zone` → `left_zone1`) that the fix guards against. - Schema tightening: `create_sdf_text` `camera_z`/`rotate`/`speed`/`intensity` now enforce their live ControlSpec ranges; `create_pointer_reactive` and `create_interaction_zones` resolutions require positive integers; `watch_parameter_changes` makes `path` optional (required only for watch/unwatch, omittable for `list`). - `narrate_set` sanitizes newlines and the record-delimiting characters (`` ` ``, `[]`, `()`) out of free-text `line`/`section`/`cue` before persisting, so `parseEntries` can no longer truncate or misparse an entry; the post-write count is derived from a pre-append read inside the same `try/catch` (never a second read that could throw out of the handler). - `create_detection_reactive` wires its advertised `reconnect_seconds` into the websocketDAT `reconnect`/`reconnectinterval` pars (probed fail-forward). - `saveNode` exec fallback now keeps a valid alternate `_n.save(...)` return path instead of always preferring the input `file` unless it matched exactly. - `tdmcp chat --resume` (headless) now **persists** the updated transcript back to the session file after each turn, so a later headless run continues from the new context instead of stale state; the misleading "Resume in the UI to load" hint is dropped (the browser UI has no matching load). - `sessionStore` validates `tool_calls` against the real `ToolCall` shape (was `z.unknown()`), removing the `as unknown as` schema cast so parsed sessions stay strongly typed end to end. - `europeana` source only tombstones on an empty keyed result when the requested `limit > 0`; an intentional zero-row sync now returns normally. - **PR #128 review pass 2 (network layout / orphan node):** these single-pass builders create every op inside one Python exec with no auto-layout (`NetworkBuilder`/`finalize` is not used), so their children stacked at the default drop point. Each now writes deterministic `nodeX`/`nodeY` so the generated network opens left→right instead of piled at the origin, and one dead node is removed: - `create_geo_visualization` no longer creates the **orphan `in1` In SOP** inside the `geo` COMP — the COMP renders the city geometry via `select1` (Select SOP), and `in1` was created but never wired or referenced. Its container children (`city` → `city_out` → `geo` → `render`, with `cam`/`light` as siblings, and the nested `select1`) are now laid out on a grid. Also fixed the pre-existing `useOptionalChain` Biome warning in `projectFeatures`. Live-validated on TD 099 build 2025.32820: the network cooks with `errors:[]` after the orphan removal. - `create_detection_reactive` positions `detector_ws`/`frames` (source) → `detect` (Script CHOP) → `detections` (Null CHOP) with the callbacks DAT below the source. - `create_fixture_control` lays the DMX chain (fixture/pad Constant CHOPs → `merge` → `rig_out` → `dmx`) in a top band and the 3D previz (`head_*` heads → `previz_cam`/`previz_light`/`previz`) in a lower band so the two halves no longer overlap. - `add_timecode_overlay` positions `fmt`/`sel` → `tc` → `comp` → `out`. - `create_synesthesia_unreal_osc` places the `controls` Constant CHOP left and the `osc` Out CHOP right. - Live-validated on TD 099 build 2025.32820: every tool-created op lands at a distinct coordinate and all five networks cook with `errors:[]`. - **PR #128 review pass 3 (re-review follow-ups):** the watch-service deleted-alias fallback now only matches a leaf name when it is **unambiguous** (two watched paths sharing a basename, e.g. `/a/level1` and `/b/level1`, no longer let `unregister("level1")` remove the wrong subscription); `create_detection_reactive` now positions its container COMP and the fallback callbacks DAT; `mapMissingWatchEndpoint` preserves the original error as `cause`; and the watch-service helpers gained Ruff return-type annotations (`_resolve_watch_key`/`_clear_emit_state`/`_match`). - **PR #128 review pass 4 (re-review follow-ups):** - Copilot `/session/save` now rejects a non-array `messages` with a structured `422 {ok:false, error:"messages must be an array"}` instead of silently coercing it to `[]` and overwriting an existing transcript while returning 200. - `--creative` no longer loses its warmer temperature when `--resume` restores a cooler saved session temperature — the resumed value is `Math.max`'d with the creative override rather than blindly replacing it. - `create_fixture_control`: the 3D previz head band's Y origin is now computed from the DMX/pad input-row count instead of a fixed `-900`, so the heads never overlap the DMX column at high fixture counts (live-validated on TD 099 build 2025.32820: 6 gapped fixtures → 11 DMX rows to y=-1600, head band starts at y=-1920, cooks with no node errors). - `add_timecode_overlay`: the container COMP is now explicitly placed (`_place` defined before the create and called immediately after) so it lands at stable coordinates instead of TD's default drop point. - `create_detection_reactive`: the container is shifted to a free X slot among the parent's existing children (`_free_x` probe) before placement, so repeated runs under the same parent no longer stack containers (live-validated: two runs landed at x=260 and x=520, no node errors). - `create_geo_visualization`: `_sop.errors()` (a newline-joined string) is now split into lines before taking the first three, instead of char-slicing the string into single characters. - `getOpTypesViaExec` now throws the reported `fatal` reason before schema validation, matching `saveNodeViaExec`/`duplicateNodeViaExec`, so a TD-side failure surfaces its message instead of a generic "Unexpected shape" error. - `tryEndpoint` is imported statically in `touchDesignerClient` instead of via a per-call `await import("./types.js")` in each fallback method. - Regression test: `unregister` on an ambiguous shared leaf basename is a no-op (both canonical watches survive). - `create_pointer_reactive` no longer leaks undocumented channels past its output Null (roadmap-to-1.0 polish, live-validated on TD 099 build 2025.32820). The `u`/`v` rename CHOPs only rename the position channels, so the Mouse In `button` rode along on every merge input; merging the three inputs then collision-suffixed the duplicate buttons (`button1`, `button2`) and passed Mouse In's `raw_u`/`raw_v` through, so the `pointer` Null carried nine channels instead of the advertised five. A Select CHOP (`channames = "u v vu vv button"`) now whitelists exactly the five documented bind points before the sensitivity gain and the output Null. Live check: the Null now cooks with exactly `['u','v','vu','vv','button']` and no node errors. - `create_step_repeat` and `create_interaction_zones` no longer hard-depend on a bundled `Mosaic.mp4` for their built-in demo (roadmap-to-1.0 polish, live-validated on TD 099 build 2025.32820). That clip does not ship on every TD build — `step_repeat` degraded silently and `interaction_zones` raised "Failed to open file". When no `source` is given, both now default to a guaranteed-present synthetic Noise TOP (a slowly drifting sparse field, so `interaction_zones` still has real frame-to-frame motion to detect) that cooks clean on any install with no external asset. An explicit `source_path` still wins unchanged. Live check: both demos built with no source arg cook with `errors: []` and no "Failed to open file". - Recipe `histogram_scope` (roadmap-to-1.0 Wave 7, gate `g3_recipes_live`) — the trace `choptoSOP` lives inside the `geo` geometry COMP while its source merge CHOP `xyz` sits at the container root, so the node's `chop` parameter must be the relative path `../xyz`, not the bare `xyz` (which TD resolved against `geo` and failed with `Invalid input CHOP ""`). Now cooks clean. Found and fixed by live end-to-end cook validation of all 10 net-new v0.7–v0.8 recipes against a real TouchDesigner (099, build 2025.32820): the other nine (`raymarch_sphere_field`, `raymarch_infinite_tunnel`, `strange_attractor_lorenz`, `ascii_render_post`, `dither_post`, `halftone_post`, `audio_glsl_uniforms`, `front_of_house_dashboard`, `sidechain_pump`) all cooked with `errors: []` unchanged. `validate:recipes` stays 50/50. - Tool-annotation directory gate: 14 tools registered without MCP safety annotations; every tool now carries `readOnlyHint` / `destructiveHint` / `openWorldHint`. `merge_vaults`, `manage_component_storage`, and `macro_recorder` (which can overwrite/delete user data or truncate a caller-named file) are now flagged `destructiveHint: true` and hidden by the `safe` tool profile (added to `SAFE_PROFILE_EXCLUDE`). - `audio_reactive_basic` recipe: the placeholder frame now reacts to audio out of the box instead of sitting at a static color. Two root causes, both live-debugged in TouchDesigner 099 build 2025.32820: the `level` analyzeCHOP's `function` was given as the integer `6`, which the bridge's menu validation rejects (menu params take names, not indices) so it silently stayed on `average` — now `"rmspower"`; and `out_color` was never wired to the level, so it never pulsed — its `colorr/g/b` are now bound to the RMS `level_null` channel via expressions (the new recipe `expr` support), so the frame pulses declaratively every cook. Verified live with a synthetic tone (RMS is 0 without a mic); the audio-reactive-visual tutorial video was re-captured from the recipe's own output. - `audio_spectrum_bars` recipe: the `spectrum` had no output length set, so the CHOP-to-TOP texture was a ~16k-wide strip and the raw FFT energy landed in a handful of bins that rendered as a near-flat 1px line. The spectrum is now clamped to 256 bins (`setmanually`/`outlength`) and the `bars` GLSL TOP has an explicit output resolution, so it renders a full-height bar visual. Live-validated in TD 099 build 2025.32820. - `optical_flow_particles` recipe was non-functional end to end (black render, flat flow field), live-debugged and fixed in TouchDesigner 099 build 2025.32820: the particleSOP now renders as point sprites (the default `prtype` "lines" draws nothing visible) with a soft circular sprite texture and visible point size; the cacheTOP previous-frame tap uses `outputindex -1` (0 returned the current frame, so the frame difference was always zero); the frame difference uses the `difference` operand plus a gain stage, and the displaceTOP midpoint is 0 so no motion means no displacement; the invalid `extforce`/`loop` parameters were removed. The flow now actually drives the particles out of the box: a topto→analyze→null CHOP chain measures motion energy and a CHOP Execute callback scales the particle turbulence/wind with it. Output composites the particles over a darkened flow texture. The camera-interactive-installation tutorial (EN+PT) now embeds a live-captured video of the recipe's own output instead of the "best seen live" hedge. ### Changed - Creative RAG `SourceSkippedError` now carries a `reason: "no-key" | "empty"` discriminator (roadmap-to-1.0 Wave 7, `rag_source_skipped_error`), so a misconfigured key-gated source never tombstones a real result. `"no-key"` (the default — existing two-arg call sites are unchanged) means the credential is absent and the upstream was never reached; `"empty"` means the source DID reach the upstream (key present) but got an untrusted zero (e.g. a rejected key or a silent outage returning HTTP 200 with no items). Both remain non-tombstoning by design — the discriminator only shapes the sync's skip log and lets callers/tests tell the two apart. The Europeana adapter now raises `"empty"` when a keyed request returns zero items for the `*` catalog query. ### Added - `watch_parameter_changes` (Layer 3) + an opt-in `param.changed` event (roadmap-to-1.0, live-validated on TD 099 build 2025.32820). Subscribe to an operator's parameters and get a `{path, par, prev, value, frame}` event on the existing TD WebSocket stream whenever a watched value changes — from a human moving a slider, a script, an expression, or a CHOP export. New bridge routes `POST`/`DELETE`/`GET /api/params/watch` back a `watch_service` subscription registry; a per-frame poller in the bridge's `events_hook` (`onFrameEnd`) detects value deltas and calls `events.broadcast`. Polling — not a Parameter Execute DAT `onValueChange` callback — was required because that callback fires only for interactive UI edits, not scripted/expression changes (confirmed live). The event is coalesced bridge-side (one emit per (path, par) per 50 ms, so a slider drag can't flood) and gated at the source by the watch registry (an empty registry stays silent), so it is delivered on the default MCP event stream without any `TDMCP_EVENTS` high-frequency opt-in. Typed client methods `watchParameters`/`unwatchParameters`/`listParameterWatches`, a `ParamWatchResult`/`ParamWatchList`/`ParamChangedEvent` Zod envelope, and a `parseParamChangedEvent` validator on the event stream. All routes survive `TDMCP_BRIDGE_ALLOW_EXEC=0` (structured, not arbitrary Python); a bridge that predates the route yields a friendly "reinstall/update the bridge" error. Live check: registered a watch on a levelTOP's `opacity`, drove it 1→0.5→0.2→0.9 and saw three `param.changed` events with correct prev/value/frame; a 20-change same-tick burst coalesced to a single event carrying the resting value. - Local copilot now auto-surfaces the Claude/Codex handoff suggestion when it hits a dead-end (roadmap-to-1.0 polish). The handoff builder + `/handoff` endpoint + UI button already existed but were only invoked manually; `runAgentTurn` now counts back-to-back tool failures and, after two in a row, emits a single non-intrusive `suggestion` event (rendered in the CLI chat and the browser copilot UI) pointing the user at the `/handoff` escape hatch. It is a suggestion line, not a forced exit — the turn continues — and it fires at most once per turn. A successful tool call resets the streak. - Regression tests pinning the Europeana `wskey`-strip lesson (roadmap-to-1.0 Wave 7, `rag_canonicalize_guid_test`): the persisted `sourceUrl`/`id` must never embed the API key and must stay stable across keys — covering both the URL-parse and the string-fallback branches of `canonicalizeGuid`, plus the new `reason: "empty"` skip path (adapter + service no-tombstone). - Six CLI / AI / library capabilities (roadmap-to-1.0 Wave 5b): - `bundle_dependencies` (Layer 3) — make a COMP self-contained: recursively scan its subtree for external file references (reusing the `collect_project_assets` scan), copy each existing asset into `/assets/`, rewrite each referencing parameter in the live network to the copied relative path, then save the COMP as a `.tox` beside its assets with a manifest. Delta vs `make_portable_tox` (`.tox`-only). CLI: `tdmcp-agent bundle-deps`. Live-validated against TD 099 (asset copied, live par rewritten to `assets/clip.mov`, `.tox` saved, no post-cook errors). - `export_externalized_tree` (library) — save a COMP as a git-diffable externalized `.tox` tree via TouchDesigner's "save external": each COMP (recursively, when `recurse`) is written to its own `.tox` with its `externaltox` parameter set, so a version-controlled project shows per-node diffs. CLI: `tdmcp-agent export-external-tree`. Live-validated on TD 099; probe-live fix — on build 2025.32820, `saveExternalTox(path,…)` is a no-op, so the tool sets each COMP's `externaltox` par first, then `saveExternalTox(recurse=…)`, and verifies each file on disk. - `tdmcp preview --inline [--watch]` — render a TOP thumbnail directly in the terminal (iTerm2 OSC 1337 / Kitty graphics protocol, with an honest ASCII fallback for plain terminals/pipes); `--watch` re-renders on an interval until Ctrl-C. Builds on the existing preview capture path. Live-validated on TD 099 (iTerm2 escape, ASCII fallback, and a 3-frame `--watch` run). - CLI error-exit taxonomy — distinct, stable process exit codes across the tool-invoking CLI paths: `0` ok, `2` usage/config, `3` TD offline/connection, `4` TD reached-but-failed (cook/validation). One `src/cli/exitCodes.ts` helper classifies failures at the exit boundary. Live-validated (offline tool → 3, bad-path tool → 4). - `copilot_session_persist` — the local copilot can now persist its transcript plus last model/tier/temperature to a JSON session file (`~/.tdmcp/copilot-session.json`) via new loopback `/session/save` and `/session/load` endpoints, and reload it with `tdmcp chat --resume` (`--session ` to choose the file). Corrupt sessions surface a `422` instead of silently starting empty. - `narrate_set` (AI) — persist a live set's narration as an append-only, timestamped decision log (with optional section + cue) to a markdown session note, recallable later; pairs with the `auto_vj_director` prompt. Delta vs `log_performance`, which writes a one-shot network snapshot rather than a running log. CLI: `tdmcp-agent narrate-set`. - Three new first-class TouchDesigner bridge REST endpoints (roadmap-to-1.0 Wave 2), each promoting proven `/api/exec` logic to a structured route that **survives `TDMCP_BRIDGE_ALLOW_EXEC=0`**, with a transparent `/api/exec` fallback for older bridges (live-validated against TD 099 build 2025.32820): - `POST /api/nodes/{path}/save` — save a node to a file (a COMP to a `.tox` component, a TOP to an image); client `saveNode(...)`, `SaveNodeSchema`. `render_output` now prefers this endpoint (falls back to exec on a 404). - `POST /api/duplicate` — duplicate a node/subtree preserving its internal wires + parameter values; client `duplicateNode(...)`, `DuplicateNodeSchema`. `duplicate_network` now prefers this endpoint (falls back to exec on a 404). - `GET /api/optypes` — the ground-truth creatable-operator list from the RUNNING TouchDesigner (every `td` family-base subclass), client `getOpTypes(...)`, `OpTypesSchema`. - `check_operator_availability` (Layer 3) — reconciles the static operator knowledge base against the live `/api/optypes` list, flagging which documented operators are actually creatable in this build vs deprecated/unavailable, plus (optionally) live-only optypes the KB doesn't yet document. CLI: `tdmcp-agent check-optypes`. - Four new stock-TouchDesigner artist/interaction tools (roadmap-to-1.0 Wave 3, no GPU/hardware required): - `create_step_repeat` (Layer 1) — brick/grid tiling of a source TOP into rows×cols with per-cell gap, position/rotation jitter, and an optional brick/masonry half-tile row offset, all computed per-cell in a single GLSL TOP shader; live controls for rows/cols/gap/jitter/brick. - `add_timecode_overlay` (Layer 2) — draw a running HH:MM:SS:FF timecode onto a source TOP as visual pixels, in `clock` (show time), `count_up`, or `count_down` modes; the formatter lives in a Text DAT module so it ticks live, composited over the source. Distinct from `sync_timecode`, which syncs a clock signal rather than drawing pixels. - `create_pointer_reactive` (Layer 1) — turn mouse/pointer position + click into a bindable creative seed: normalized u/v + velocity + button on a `pointer` Null CHOP ready for `bind_to_channel`, with an optional built-in feedback-field demo the pointer visibly pushes. - `create_interaction_zones` (Layer 1) — define N rectangular motion zones over a camera input; each zone emits a `*_state` (active) and `*_dwell` (seconds active) channel on a `zones` Null CHOP ready to fire cues, with a live Threshold knob. - Six new stock-TouchDesigner generator tools (roadmap-to-1.0 Wave 4, all Layer 1, no GPU/hardware required): - `create_terrain` — a dedicated procedural heightmap landscape: an animated Noise TOP height field displaces a subdivided Grid SOP along Z in a GLSL vertex-displacement MAT (real 2.5D geometry, elevation-shaded from a low→high colour ramp), with an optional translucent water plane and camera-distance fog. Distinct from `create_visual_system`'s "terrain" keyword (which only maps to the noise_landscape recipe). Live Height/Drift/WaterLevel/Zoom controls. - `create_asemic_writing` — generate a page of procedural asemic writing: random-but-writing-like glyph strokes that flow left-to-right along stacked baselines but spell nothing, drawn by a Script SOP pen (italic slant, per-stroke jitter, pen-lifts), tubed and rendered with an ortho camera. Deterministic per seed; live Jitter/Slant/Thickness/Seed controls. - `create_sdf_text` — raymarch a text string as an extruded signed-distance-field slab: a Text TOP glyph mask feeds a GLSL raymarcher so the letters read as solid, lit, rim-highlit 3D volumes that can spin. Distinct from `create_sdf_field` (primitive CSG only, no text) and `create_text_3d` (mesh-extruded). Live CameraZ/Speed/StepCount/Intensity/Rotate/Fill/Edge/ Background controls. - `create_vertex_displacement_mat` — a true vertex-shader displacement GLSL MAT that offsets mesh vertices along their normals by procedural 3D noise or a sampled texture, assignable to your own Geometry COMP or previewed on a demo sphere. Distinct from the TOP-space warps `create_depth_displacement` / `create_displacement_warp` (which push pixels, not vertices). Live Amount/ Frequency/Speed controls. - `controlled_disorder_grid` — a grid of quads (or outlined cells) with a single order↔chaos `disorder` knob (0 = a perfect grid → 1 = full chaos) that scales per-cell position/rotation/scale jitter together, each hashed from the cell index in one GLSL TOP (the classic generative-design "controlled randomness" / Schotter study). Live Disorder knob + colour swatches. - `create_blob_trace` — trace a blob/silhouette into a vector contour outline: monochrome → blur → threshold (blob mask) → optional edge → Trace SOP → wireframe render. The contour-trace complement to `create_vector_lines` and `export_sop_to_svg`, and distinct from `create_blob_reactive` (tracking, not outline). Live Threshold/Blur/LineWidth controls. - Note: `create_l_system` was **not** built — `create_growth_system` already ships a complete Lindenmayer turtle-graphics generator (axiom + weighted stochastic rules + iterations → polyline tree), so the item is superseded. - Five new integration/creative tools (roadmap-to-1.0 Wave 5a), all live-validated against TD 099 build 2025.32820 (each built a real node network and cooked with `errors: []`): - `create_fixture_control` (Layer 1) — a moving-head lighting rig with BOTH a DMX/Art-Net output chain AND a 3D previsualization: each fixture is an 8-channel movingHead8 Constant CHOP block (pan/tilt/dimmer/rgb/strobe/gobo, padded + merged into a dmxoutCHOP) plus a Geometry COMP head with a tube-cone beam whose pan→ry / tilt→rx rotation is expression-driven straight from that fixture's DMX pan/tilt channels, rendered under a camera+light Render TOP. Adds the live 3D preview on top of `create_dmx_fixture_pipeline` (DMX-out only). - `create_detection_reactive` (Layer 1) — turn object/person detection into control channels with **no CUDA**: either a `websocket` backend that subscribes to an external detector process streaming JSON detections, or an `onnx` CPU Script CHOP scaffold (onnxruntime, `CPUExecutionProvider`). Both emit a stable Null CHOP contract — presence, count, and per-object normalized bboxes (`objN_x/y/w/h/score`) — ready for `bind_to_channel`. (Detection idea inspired by the MIT-licensed TDYolo; no code copied.) - `create_geo_visualization` (Layer 1) — project GeoJSON/OSM Point/LineString/ Polygon features via a Mercator projection normalized to a unit box, then a Script SOP lays out point clouds + polylines (optionally extruded into 3D ribbon "buildings" from each feature's `height`), wrapped in a Geometry COMP under a camera+light Render TOP. Emits an ODbL/OpenStreetMap attribution note. - `scaffold_vj_deck` (Layer 2) — one-call orchestration that composes `create_decks` (A/B mixer + crossfader), `create_control_surface` (on-screen crossfade + per-deck gain faders), and `create_external_io` (a midiinCHOP bound to the same crossfader/gain params) into one MIDI-mappable VJ deck UI container. The deck-scaffold layer on top of the `create_decks` primitive. - `create_synesthesia_unreal_osc` (Layer 2) — named OSC-out preset maps for Synesthesia (`/syn`, port 6448) and Unreal Engine (`/unreal`, port 8000): builds a Constant CHOP whose channels are named `/` so an oscoutCHOP emits the exact addresses the target app expects, with overridable controls/prefix/host/port. The preset layer on top of `create_external_io` osc_out. - Artist-friendly docs information architecture: the guide sidebar is now 7 collapsible categories (identical EN/PT structure derived from one descriptor), a "What do you want to make?" goal-card guide home is the new Guide entry point, and a bilingual tutorial track ships with 4 step-by-step prompt tutorials (audio-reactive visual, camera-interactive installation, VJ set with a timeline, generative art loop) — three of them live-validated in TouchDesigner with captured preview videos embedded. - Drag-and-drop bridge install: `npm run build:bridge-tox` generates a tag-pinned, self-bootstrapping `tdmcp_bridge_package.tox` (via the running bridge's `/api/exec`, so no Textport for the maintainer either) to attach to the GitHub Release. End users then install the bridge by dragging the `.tox` into a project and clicking **Install** — no Textport, no Preferences, no clone. The `td/README.md` "Easiest install" now leads with this path. - Recipe parameter expressions: a recipe `parameters` entry can now carry an `expr` (Python expression) so `apply_recipe` binds the parameter in expression mode instead of setting a constant. `op('')` references are rewritten to the real created paths at build time, and the bridge param-mode endpoint is used with an `/api/exec` fallback for older bridges. ## [0.12.0] - 2026-07-04 ### Added - Idempotent node creation: `create_td_node` / `create_node_chain` now reuse an operator that already exists at the target path with the same name and type (reported as `already_existed: true`) instead of failing or auto-renaming, so agent retries are safe. A name collision with a _different_ type stays an explicit error. - Automatic undo blocks: every mutating bridge request is wrapped in one TouchDesigner `ui.undo` block, so the artist can Ctrl+Z a whole agent action in a single step. - Menu parameter validation: setting a fixed-Menu parameter to an unknown value (which TouchDesigner would silently coerce to index 0) now returns an explicit error listing the valid menu entries, across `update_td_node_parameters`, `set_parameters_batch`, and `set_parameter_expression`. - `get_preview` gains a `sample_grid` option (2–16): return an N×N grid of RGBA samples plus per-channel min/max/mean stats as JSON — a 10–50× cheaper way to check whether a TOP's output is alive than encoding a full image. NaN/Inf from HDR TOPs are sanitized to null. - `get_preview` gains `pre_pulses` (pulse parameters in the same frame just before capture, validated all-or-nothing) and `delay_frames` (defer the capture and collect it later by `job_id`), so transient events can be captured reliably. - `arrange_network` and the shared layout path now move each node's docked DATs by the same delta as the node (`include_docked`, default on), mimicking an interactive drag. - Token-economy guidance added to the most-used read tools and the server's `initialize` instructions. - `delete_td_node` gains a `mode`: `bypass` disables an operator (reversible) instead of destroying it, a safer middle ground; `delete` stays the default. `TDMCP_YOLO=1` is surfaced in result reporting for future confirmation gates. - Bridge back-pressure: after a request runs slower than `TDMCP_SLOW_THRESHOLD_MS` (default 5000), subsequent requests are shed with HTTP 503 + `retry_after` for a `TDMCP_COOLDOWN_MS` window (default 2000) so TouchDesigner's cook loop can recover; the client surfaces this as a typed, retryable `TdBackpressureError`. - Streamable HTTP transport hardening: reject a present, non-loopback `Origin` with 403 (anti DNS-rebinding, alongside the existing Host allowlist) and a POST with a non-JSON `Content-Type` with 415. - `get_tutorial` splits large documents into sections: with `include_content` the body is capped (~30K chars, truncated at a line boundary) and comes with a `sections_available` list; pass a `section` title to return just that part. - `search_operators` now surfaces the offline menu catalog (menu options on matched Menu parameters) and stamps results with a `data_version` (which TouchDesigner build the data reflects) plus a `stale_hint` when a connected TouchDesigner reports a different major version. - `focus_network_editor` (Layer 2): pan/zoom TouchDesigner's Network Editor to frame given operators — a "follow" move so the artist sees what the agent just built. UI-only; new `POST /api/editor/focus` bridge endpoint. - Legacy pre-shared bearer auth on the Streamable HTTP transport: set `TDMCP_HTTP_AUTH_TOKEN` to require `Authorization: Bearer ` on every request; missing/invalid credentials get a 401 with a `WWW-Authenticate: Bearer` challenge. This static credential is not OAuth. Off by default. - `npm run smoke`: an offline smoke harness that boots the server, completes a real in-memory MCP handshake, and verifies the tool surface + graceful offline degradation without a running TouchDesigner. - `npm run contract:gen`: export a portable "skill contract" — a host-agnostic JSON snapshot of every tool (name, description, JSON-Schema inputs) + prompts. - Add `get_dat_content` (CLI `dat-get`), a read-only Layer 3 tool that pages a DAT's text or table content (offset/limit, optional header, preview rows, and a `truncated`/`row_range` window) so agents can inspect large DATs without raw Python. - Add `get_parameter_menu` (CLI `params-menu`), a read-only Layer 3 tool that live-fetches a menu-style parameter's `menuNames`/`menuLabels` and current value from the bridge, with a loud-warned bundled-knowledge fallback when raw exec is unavailable. Patterns inspired by Derivative's official TouchDesigner TDMCP (Shared Use License); reimplemented independently. ### Changed - Add an optional `auto_layout` flag to `rebuild_network` that runs the dataflow auto-layout over the spec's nodes before rebuild, overriding manual x/y. Patterns inspired by Derivative's official TouchDesigner TDMCP (Shared Use License); reimplemented independently. - Extend `set_parameter_expression` with `reset` and `unbind` assignment modes (reset a parameter to its default / freeze a driven value to a constant); these two modes require `TDMCP_BRIDGE_ALLOW_EXEC=1`. Patterns inspired by Derivative's official TouchDesigner TDMCP (Shared Use License); reimplemented independently. ### Security - Harden the TouchDesigner bridge request handler with a loopback-only address scope by default: a request from a non-loopback peer is rejected (HTTP `403`) before routing, authentication, or any tool runs, unless LAN exposure is explicitly enabled with `TDMCP_BRIDGE_ALLOW_LAN=1` in TouchDesigner's environment. This complements the existing `Origin`/`Host` header guards with an unforgeable peer-address check. Pattern inspired by Derivative's official TouchDesigner TDMCP ("Address Scope") under the Shared Use License; reimplemented independently in our Python bridge. ## [0.11.0] - 2026-06-25 ### Added - Add a Claude Code plugin marketplace entry for tdmcp with a stdio-pinned MCP server launch configuration. - Import TouchDesigner knowledge from Bottobot into MCP resources for version history, compatibility notes, operator workflow guidance, technique packs, TD class families, and experimental build data; add read-only agent tools for cross-surface knowledge search and operator workflow lookup. - Expand `search_operators` with category/subcategory filters, exact/tag modes, parameter metadata search, version compatibility filtering, facets, zero-result tips, and explicit validation for unknown categories or TouchDesigner versions. - Add `compare_operator_docs` and `search_python_api` read-only knowledge tools so agents can compare operator documentation and search TouchDesigner Python classes, methods, and members without guessing resource URIs. - Add `suggest_operator_chain` and `plan_td_version_migration` read-only tools so agents can turn offline workflow/compatibility knowledge into operator-chain plans and TouchDesigner upgrade checklists before touching a live project. - Add `validate_operator_chain` and `draft_recipe_from_operator_chain` read-only tools so agents can preflight operator chains against offline docs/version compatibility and turn validated chains into `RecipeSchema` drafts without mutating TouchDesigner. - Add `get_technique_detail`, `draft_recipe_from_technique`, and `get_tutorial` read-only knowledge tools so agents can inspect Bottobot-derived technique and tutorial material and turn GLSL techniques into `RecipeSchema` drafts offline. - Add the Kinect wall harp command/tool with FreenectTD-oriented wall-touch tracking, external Kinect bridge support, calibration diagnostics, laser-line visuals, and clean sine-based audio output. - Add an English and Portuguese physical-installations guide that captures the Kinect wall harp lessons as a reusable hardware/projector checklist and next-slice backlog. - Add a post-implementation learning harness that studies shipped tdmcp features and turns real code, runtime, review, docs, and hardware lessons into routed improvement backlogs. - Add normalized helper status payloads and optional `--status-json` output to the Kinect wall harp libfreenect2 bridge. - Surface Kinect wall harp bridge health inside generated TouchDesigner projects through a `bridge_status` DAT driven by the same normalized status JSON. - Add a generated `bridge_status_chop` to expose bridge health as numeric TouchDesigner channels for panels, overlays, and logic. - Add a reusable external-sensor status-surface helper so future Layer 1 tools can generate consistent bridge health DAT/CHOP diagnostics. - Add local TouchDesigner operator-health status surfaces to `create_live_source` and `create_depth_silhouette` so camera, depth, NDI, Syphon/Spout, screen-grab, and video-stream inputs expose `source_status` and `source_status_chop` diagnostics without an external bridge. - Add `diagnose_hardware_environment`, a read-only Layer 3/MCP/agent preflight for bridge reachability, display/projector topology, and generated `source_status` / `bridge_status` DAT health checks. - Add `draft_recipe_from_tutorial` as a read-only Layer 3/CLI/local-copilot tool that extracts conservative operator chains from embedded tutorials and drafts `RecipeSchema` JSON offline; harden tutorial content handling so structured Bottobot tutorial sections and code blocks flatten consistently for retrieval and search. - Add English and Portuguese cookbook examples for offline TouchDesigner knowledge workflows, including tutorial-to-recipe drafting and operator-chain compare/validate/draft loops with live checks marked `UNVERIFIED-pending-td`. - Expand the English and Portuguese prompt cookbook with newer TouchDesigner examples for live video ingest, phone gesture control, performance controls, stipple point clouds, time echo, DMX fixture routing, and fulldome/cubemap output; include TD-captured videos for the hardware-free time-echo and dome examples. ### Changed - Deduplicate ~20 copy-pasted hex-color helpers across Layer 1 generators into a shared `src/tools/util/color.ts` (`parseHexColor`/`hexToRgb`/`hexToRgbTuple`/ `rgbToHex`), removing ~268 duplicated lines while preserving each tool's exact fallback color and `#rgb` shorthand policy. - Improve tool-description quality (Glama "Disambiguation" + minimum-tool score): add code-verified "use X instead of Y when Z" guidance to the overlapping particle, audio, feedback, text, and scope tools, and enrich the weakest library/recipe tool descriptions with usage context and read-only/writes notes. - Mark the MCPB `TDMCP_BRIDGE_TOKEN` user-config field as `sensitive` so Claude Desktop masks it and stores it in the OS keychain instead of plain text. ### Fixed - Factor Kinect wall harp JSON-line helper supervision into a reusable external helper supervisor while preserving libfreenect2 stall restart coverage. - Harden the external-helper supervisor stall-restart unit test against Node subprocess startup jitter under the full parallel Vitest suite. - Stabilize the JS/TS cognitive-complexity ratchet with signature-based baseline keys, align the advertised Node engine floor with the ESLint dependency chain, and expand offline coverage tests for the coverage/complexity wave. - Keep Glama/pnpm Docker builds warning-free by moving pnpm install policy into `pnpm-workspace.yaml`, pinning the Vite/Cheerio resolutions there, and keeping the Shader Park compiler as an optional peer. - Clear the npm audit report by updating vulnerable Vitest, Vite, VitePress and esbuild transitive dependency resolutions. - Point the `doctor --fix` remediation hints at `tdmcp-agent doctor` (the binary that hosts the health doctor); `tdmcp doctor` routes to the package-library doctor, so the old hints sent failing users in a circle. - Stop the agent CLI from suggesting the exact unknown command the user typed (e.g. `tdmcp-agent exec` no longer prints `Did you mean "exec"?`). - Pin the bootstrap one-liner in `llms-install.md` and `tdmcp-install-prompt.md` to the released tag (they were stuck on `main`) and add both to the version-sync `bootstrapPinPaths` so they stay pinned on future releases. - Stage every file `sync-manifest-version.mjs` rewrites (manifests + all bootstrap-pin docs) from the script itself, and drop the drift-prone hand-maintained `git add` list from the `version` npm script — so the release commit/tag no longer omits the rewritten bootstrap pins. - Sync the TouchDesigner bridge `BRIDGE_VERSION` and `get_td_info` expected bridge version to the package version during release prep, so users running an old bridge get the intended `bridge_stale` reload warning after upgrading. - Correct the advertised tool count (286 → 332) on the README and docs landing page. - Remove a dead `code-quality` CI step that diffed the gitignored `docs/reference/tools.md` and could never fail. - Fix two tool-description inaccuracies: `image_to_particles`' default source image and `create_video_scopes`' TD-099-unsupported histogram panel. - Make `npx skillsafe scan .` (the SafeSkill scan documented in `.safeskillignore`) usable by excluding `node_modules/`, `.git/`, `.claude/` and `_workspace/` — without them the CLI ran the Node heap out of memory walking dependencies. Also reword a `` placeholder in `docs/reference/cli.md` that SafeSkill flagged as a fake-XML context-boundary (a false positive in a CLI usage example). ## [0.10.0] - 2026-06-23 ### Added - **Recipe library depth (G3) — roadmap-to-1.0 campaign, Wave 6** — 18 new first-party recipes (32 → 50; `npm run validate:recipes` 50/50). Ten net-new fill v0.7–v0.8 generator gaps: `raymarch_sphere_field` + `raymarch_infinite_tunnel` (SDF), `strange_attractor_lorenz`, `histogram_scope`, `ascii_render_post`, `dither_post`, `halftone_post`, `audio_glsl_uniforms`, `front_of_house_dashboard` (dashboard-v2), `sidechain_pump`. Eight new Layer-1 orchestrator twins: glitch, kaleidoscope, slime simulation, spectrum, waveform, tempo-sync, layer-mixer crossfade, slit-scan. All grounded in real optypes and offline-validated against `RecipeSchema`; live end-to-end cook validation is UNVERIFIED-pending-td. Orchestrators whose behavior is callback/pulse/hardware-driven (not faithfully reproducible as static JSON) are deferred to post-live twin authoring. - **Milestone 5 — AI Show Director mixer scene arming (dry-run MVP, offline) — roadmap-to-1.0 campaign, Wave 3** — new `arm_mixer_scene` ShowIntent variant for operator-approved Soundcraft Ui24R show/snapshot/cue arming, separate from `arm_effect`. The MixerScenePolicy returns `require_approval` for catalog-backed requests and **never `allow`** in the MVP; it `block`s on missing manifest, unknown / LLM-invented `scene_id`, unknown `mixer_id`, unresolved `setlist_ref`, unsupported target, changed catalog hash, or an unsafe scene diff — and `mixer_gain`/`pa_mute`/`audio_routing` stay blocked. New `src/automation/mixerSceneCatalog.ts` (trusted venue scene catalog / safety manifest + content hash) and `src/automation/mixerSceneAdapter.ts` (adapter interface + dry-run backend returning `hardware_changed:false`; Companion / direct-node return not-configured — no hardware client is constructed). Approval re-runs policy and emits the dry-run plan (`dry_run_only:true`) built from the catalog; old effect approvals stay backwards-compatible. Companion live backend + direct Node bridge remain quarantined pending bench/hardware validation. Safety-QA verified all six boundary contracts; 215 mixer/show-director tests pass. - **Coverage CI gate (G2) + exec-off smoke (G4) + Connectors Directory prep (G6) — roadmap-to-1.0 campaign, Wave 2** — the coverage harness is now a CI gate: `vitest.config.ts` thresholds ratcheted to the measured no-regression floor (functions 82→83, lines 85→86; statements 84 / branches 70 unchanged) and the CI `Test` step now runs `npm run test:coverage`. New `docs/reference/coverage-harness.md` documents the gate and the tracked +5pp target (lines ≥ 91, branches ≥ 75). New `tests/smoke/execOff.test.ts` proves every Layer-1 + Layer-2 tool registers with raw Python exec disabled (`TDMCP_RAW_PYTHON=off`): 132 L1 + 78 L2 register cleanly, only `create_python_script` is hidden by its gate; a dedicated CI smoke runs it exec-off. The Connectors Directory submission package was re-verified (privacy EN+PT current, `build:mcpb` produces a schema-valid 18.2 MB `.mcpb`, no stale `.dxt` refs) with a full form-answer draft prepared; directory acceptance remains an external step. - **Docs completeness (G5) + API stability pin (G1) — roadmap-to-1.0 campaign, Wave 1** — new per-arc guides for the v0.7/v0.8 work that lacked one: `docs/guide/show-timelines.md` (timelines & setlists), `dashboard-foh.md` (front-of-house), `session-profile.md` (session profile & corpus learning), `mediapipe-adapters.md` (face/hand/segmentation/pose) and `mcp-resources.md` (the `tdmcp://…` resource families), plus `generators.md` — a "what it builds + when to reach for it" paragraph per cookbook-referenced Layer-1 generator. All EN + PT, wired into the VitePress nav. New `docs/reference/API_STABILITY.md` pins the v1.0 API contract (the `ToolContext` shape + each tool's Zod `inputSchema`) and the one-minor-warn / next-minor-remove deprecation policy, cross-linked from the Tool API contract page. `README.md` now cross-links the awesome-touchdesigner list and the tdmcp Glama listing. Docs-only: `docs:build`, `docs:gen` (318 tools), `typecheck` and Biome pass. - **Hand hologram controls (Layer 1 + Layer 2, offline-tested)** — new `create_hand_gesture_bus` builds a stable, reusable MediaPipe-hands CHOP bus with palm openness, float anchor, active-hand lock, dropped-frame hold, debounced opposite-hand pinch, scale, light and audio channels. New `create_hand_hologram` consumes that bus to build a synthetic-safe palm hologram: a translucent GLSL cube floating above an open palm, with glow, rotation, optional synth/device audio and pinch-driven scale/brightness. The CLI aliases are `hand-gesture-bus` and `hand-hologram`. Offline tests, docs generation, build, recipes and bridge unit tests pass; live TD cook validation is pending a reachable bridge. - **Cross-RAG ranking — fuse Creative RAG + Project RAG via Reciprocal Rank Fusion (opt-in)** — a pure helper (`src/llm/crossRagFusion.ts`) that merges the two opt-in local RAG corpora into one ranked list using **Reciprocal Rank Fusion** (`rrf(d) = Σ 1/(k + rank)`). RRF is rank-based and therefore scale-free, which is required because the two `score` fields are incomparable (Creative = cosine `0..1`; Project = `cosineSim * composite`). Fusion is gated by `ragEnabled && projectRagEnabled && ragFusion` and only activates when **both** corpora return results — otherwise it is a no-op passthrough, so behaviour is byte-for-byte identical to before when the flag is off. Wired into `tdmcp ask`'s context-injection path (the fused reference block replaces the single-corpus creative block when active). Two new env vars: `TDMCP_RAG_FUSION` (boolean-ish, default off) and `TDMCP_RAG_FUSION_K` (RRF k, positive int 1..1000, default 60). No new MCP tool, no bridge, no dependencies. - **Project RAG — awesome-list discovery source (suggest-only, opt-in, experimental)** — a read-only discovery queue parsed from the `monkeymonk/awesome-touchdesigner` README (`src/projectRag/sources/awesomeList.ts`). New `tdmcp project-rag sources --discovery` lists candidate TD repos/links for an operator to review; it is deliberately **not** a live sync `SourceAdapter` — it never enters `resolveProjectSources`, never clones repos, never downloads binaries, and never emits index-eligible cards. Every item is hard-stamped `license: "Unknown"` / `licenseConfidence: "unknown"` / `suggestOnly: true` and carries mandatory provenance (`sourceName`/`sourceUrl`/`discoveredAt`), so the license-gate stays intact. Only `https://` links survive; binary URLs (`.tox`/`.toe`/`.zip`/`.7z` and `/releases/download/`) are dropped. When the README can't be fetched/parsed the queue degrades to a clean skip (`SourceSkippedError` → exit 0, never a tombstone). New service method `ProjectRagService.listDiscovery()`; `--json` supported. No new env var. - **Project RAG — Interactive & Immersive HQ tutorial source (CC-BY-NC-SA, opt-in, experimental)** — a markdown-text `SourceAdapter` (`src/projectRag/sources/interactiveImmersive.ts`) that ingests the chapter markdown of the [Interactive & Immersive HQ "Introduction to TouchDesigner" manual](https://github.com/interactiveimmersivehq/Introduction-to-touchdesigner) as `tutorial` cards. The manual is **CC-BY-NC-SA-4.0** (non-commercial + share-alike + attribution, declared in the repo README), so the source is **opt-in / default OFF**, enabled with `TDMCP_PROJECT_RAG_IIHQ=1` (`TDMCP_PROJECT_RAG_IIHQ_REF` overrides the branch). It ingests **markdown TEXT only** (meta + body, capped) and **never downloads binaries** — `img/`, `TouchDesigner Example Files/`, and all non-`.md` paths are excluded, and `CC-BY-NC-SA` binaries are hard-denied in the license policy regardless of the allowlist. Every emitted item carries mandatory provenance + `authors: ["The Interactive & Immersive HQ"]` + `license: "CC-BY-NC-SA"` / `licenseConfidence: "declared"`, and a concise **license banner** (`CC-BY-NC-SA · non-commercial, share-alike, attribute The Interactive & Immersive HQ`) now renders on every result in both CLI search (`tdmcp project-rag search`) and the MCP `project_rag_context` prompt. Fetch failures (trees non-2xx / network / timeout / empty) degrade to a clean `SourceSkippedError` (never a tombstone). Adds `CC-BY-NC-SA` to the Project RAG license enum/schema/CLI/resource surfaces and the SPDX classifier. - **Project RAG — derivative-local source (opt-in, experimental)** — a local-disk `SourceAdapter` (`src/projectRag/sources/derivativeLocal.ts`) that discovers an installed TouchDesigner and indexes its shipped Palette / OP Snippets `.tox`/`.toe` examples. Install root resolves from `TDMCP_PROJECT_RAG_DERIVATIVE_ROOT` first, then per-OS defaults (macOS/Windows/ Linux); when no install is found it degrades to a clean skip (`SourceSkippedError`, never a tombstone). Enumerates + reads metadata only — it **never executes** a `.toe`/`.tox` — and stamps every card with the local Derivative EULA license (local-only, no redistribution / no `binaryUrl`) plus mandatory provenance, so the license-gate stays intact. `listSources()` now reports `derivative-local` as `ready`. - **Project RAG — bridge `POST /api/project/load` endpoint (F3 analyzer upgrade)** — a first-class quarantine-bridge endpoint (`td/modules/mcp/services/project_load_service.py`) that loads a `.toe`/`.tox` at an absolute path inside the on-:9981 quarantine TD and returns a typed envelope `{ root_path, node_count, errors[], preview_b64? }`. New typed client method `TouchDesignerClient.loadProject()` with a Zod envelope in `validators.ts`; the F3 `bridgeAnalyze` extractor now prefers this endpoint and falls back to the exec-style `project.load` path only on a missing route (404), rethrowing real validation/timeout/connection errors unchanged. The endpoint validates the path (absolute, `.toe`/`.tox`, exists) and is not arbitrary Python, so a hardened `ALLOW_EXEC=0` bridge can still open its own artifact. `.toe` artifacts load via `project.load`; `.tox` artifacts import into a fresh COMP via `COMP.loadTox` (so the analysis targets the component, not the host project). The route is **default-DENY** bridge-side and only honored when the instance is explicitly marked as a throwaway quarantine (`TDMCP_PROJECT_RAG_QUARANTINE=1`) — installing the bridge on a normal TD can never let a direct caller load over the open project, independent of `TDMCP_BRIDGE_ALLOW_EXEC`. - **Project RAG — MCP prompts, resources, copilot tool & CLI cross-link (opt-in, experimental, F4)** — the AI surface for the local Project RAG repertoire lands. New MCP prompt `project_rag_context` (`src/prompts/projectRagContext.ts`): runs `ctx.projectRag.search()` over the user query and returns a top-k card listing (title + license + `tdmcp://project/cards/{id}`) as authoritative reference; silently degrades to a stock prompt when Project RAG is off, with `query`/`k`/`license` args. New MCP resource `tdmcp://project/sources` (`src/resources/projectRagSourcesResource.ts`): lists configured sources + status (`ready`/`skipped`/`planned`/`failed`) so the agent knows what is not indexed before searching. New read-only LLM copilot tool `project_rag_search` (`src/llm/projectRagSearchTool.ts`, `mutates: false`): exposed in every tier of `resolveTools(...)` only when `ctx.projectRag` is defined — when disabled, the tool is absent from the agent catalog, not refused at call time. New `tdmcp creative-rag search` cross-link tip (`src/creativeRag/crossLink.ts`): when results are sparse (≤ 2) and `TDMCP_PROJECT_RAG_ENABLED=1`, prints a one-line stderr suggestion to try `tdmcp project-rag search ""`; suppressed in `--json` mode so machine output is unchanged. All offline, additive — gated by `TDMCP_RAG_ENABLED=1 && TDMCP_PROJECT_RAG_ENABLED=1`. - **Project RAG — bridge-quarantine analysis (opt-in, experimental, F3)** — two artifact analyzers for downloaded `.toe`/`.tox` files, both fully isolated from the user's main TouchDesigner. (1) Static analyzer `runToeExpand` (`src/projectRag/extractors/toeExpand.ts`): wraps an external `toeexpand`-style CLI in a quarantine subprocess (`spawn()` only, reduced env of `PATH`/`HOME`/`LANG=C.UTF-8`, 30 s hard timeout, group-kill via `detached:true` + `kill(-pgid)`, UUID temp cwd with `try/finally` cleanup); returns `ok`/`failed`/`skipped` (the latter when the binary is not on `PATH`). Configurable via `TDMCP_PROJECT_RAG_TOEEXPAND_BIN` and `TDMCP_PROJECT_RAG_ANALYZE_TIMEOUT_MS`. (2) Dynamic analyzer `runBridgeAnalyze` (`src/projectRag/extractors/bridgeAnalyze.ts`): instantiates a NEW `TouchDesignerClient` bound to `TDMCP_PROJECT_RAG_BRIDGE_PORT` (default **9981**, refuses `9980`), reachability-probes via `getInfo`, then calls `getNetworkErrors("/")` and `getPreview("/project1/out1")`. Offline bridge degrades to `skipped` (not `failed`) — `exit 0` is preserved as the safe default. New CLI surface: `tdmcp project-rag analyze ` (one-shot ad-hoc), `tdmcp project-rag bridge install` (docs-driven walkthrough + reachability probe), and `tdmcp project-rag sync --bridge` (post-sync analyze pass over every permissive-licence card with a persisted binary; idempotent — already `analysisStatus: ok` cards are skipped). Card schema v2 gains `analysisStatus` + `analysisReason` (excluded from `contentHash` so unchanged source content remains a cache-hit even after analysis). All 18+ new vitest cases are offline (no msw, no TD required) — live validation on a real 9981 bridge is unverified until a user provides one. - **Project RAG — multi-source + tuned scoring (opt-in, experimental, F2)** — `DBraun/TouchDesigner_Shared` (GPL-3.0) added to the default seed list with the copyleft flag rendered in CLI/MCP search output as `GPL-3.0 · copyleft`. New `github-topic` source scanner (default topics: `touchdesigner-components`, `touchdesigner-tool`, `touchdesigner-tools`, `touchdesigner`) with hard filters (SPDX allowlist, min stars, recency, per-sync cap 25) — opt-in `TDMCP_PROJECT_RAG_GH_TOKEN` lifts the 60 req/h unauthenticated rate-limit. Scoring composite tuned: copyleft tie-breaker penalty (−0.05, never blocks) + curated-source reliability boost (+0.10) for the default tdmcp seed list; ground-truth set (`_workspace/campaign_project_rag/scoring_ground_truth.json`) yields 9/10 top-1 hit-rate. New CLI: `sync --topic --cap N`, `sync --topic off`, `reindex --rescore` (recomputes `score.composite` without re-embedding). Configurable via `TDMCP_PROJECT_RAG_GITHUB_TOPICS` and `TDMCP_PROJECT_RAG_TOPIC_CAP`. - **Project RAG — MVP first source (opt-in, experimental, F1)** — the `github-repo` adapter is now live. Default seed is [`torinmb/mediapipe-touchdesigner`](https://github.com/torinmb/mediapipe-touchdesigner) (MIT); override or extend via `TDMCP_PROJECT_RAG_GITHUB_REPOS=owner/repo[@ref],…`. Fetched entirely through the GitHub REST API (no local `git clone`): metadata + SPDX license detection + README body + top-level `.tox`/`.toe` listing, with the binary downloaded only when the configured license allowlist permits. `tdmcp project-rag {sync,index,search,info,sources}` now runs the full pipeline against the seed; `search` reuses the Creative RAG `OllamaEmbeddingsClient` (`nomic-embed-text`) for embeddings. New basic composite scoring (`technical · 0.45 + license · 0.25 + freshness · 0.15 + reliability · 0.15`, weights tunable via `TDMCP_PROJECT_RAG_SCORE_WEIGHTS`). Optional `TDMCP_PROJECT_RAG_GH_TOKEN` raises the GitHub rate-limit from 60 req/h to 5000; the adapter raises a typed `SourceSkippedError` (never a silent zero-items result) when the anonymous quota is exhausted, so prior cards from the source are never tombstoned by accident. Provenance + license remain mandatory on every persisted card. - **Project RAG foundations (opt-in, experimental, F0)** — local TouchDesigner *project/component/snippet/tutorial* repertoire, sibling to Creative RAG with mandatory `provenance` + `license` on every card. New `tdmcp project-rag {sources|sync|index|search|info}` CLI subcommand (F0 ships the foundations only: gating, schema v2, JSONL store, service skeleton — source adapters land in F1). New read-only MCP resources `tdmcp://project/cards/{id}` and `tdmcp://project/search{?q,k,license,type,tags,operator}`, registered only when both `TDMCP_RAG_ENABLED=1` and `TDMCP_PROJECT_RAG_ENABLED=1` are set (project flag defaults ON when RAG is on). Data dir is isolated at `/project/` — never mixed with Creative RAG cards. Extended `ProjectRagLicense` enum covers SPDX permissive + copyleft + Derivative-EULA + Proprietary-* alongside the existing CC0/CC-BY/Unknown set, with `licensePolicy` matrix that refuses binary storage for Derivative-EULA/Proprietary-*/Unknown/Restricted even when allowlisted. Bridge-quarantine analysis (F3) remains OFF by default; when enabled it will use a separate `TouchDesignerClient` on dedicated port `TDMCP_PROJECT_RAG_BRIDGE_PORT=9981`, never the user's active 9980 bridge. Inert when off; zero impact on existing flows. - **Creative RAG local (opt-in, experimental)** — a local-only creative repertoire of open-licensed artworks, artists and techniques. New `tdmcp creative-rag {sync|index|search}` CLI subcommand and read-only `tdmcp://creative/cards/{id}` + `tdmcp://creative/search?q=...` MCP resources. Ingests four live museum sources (Art Institute of Chicago, The Met, Rijksmuseum, Cleveland Museum of Art) plus nine planned-source stubs, embeds locally via Ollama (`nomic-embed-text`), and persists a local JSONL index. Every result carries source URL, license and rights notes through a coded license policy. Off by default; enable with `TDMCP_RAG_ENABLED=1` (`TDMCP_RAG_DATA_DIR`, `TDMCP_RAG_OLLAMA_URL`, `TDMCP_RAG_EMBED_MODEL`, `TDMCP_RAG_LICENSE_ALLOWLIST`). Repertoire context only — no bridge, DMX, or Python exec. See [Creative RAG](docs/CREATIVE_RAG.md). - New runtime dependency `yaml` (license-policy / source-config parsing). - **Creative RAG — three new live sources.** Smithsonian Open Access (key-gated via `TDMCP_RAG_SMITHSONIAN_KEY`; `media.usage.access:"CC0"` ⇒ CC0), Wikimedia Commons (keyless; machine-readable `extmetadata.License` mapping), and Europeana (key-gated via `TDMCP_RAG_EUROPEANA_KEY`; per-item `rights` CC/RS URI → license; the wskey appended to each `guid` is stripped so it never lands in the persisted `sourceUrl`/`id`). All three verified against a real sync. Key-gated sources read their key in-source from the environment, never log it, and skip cleanly (no tombstoning) when the key is unset. - **Creative RAG — embedding batching.** `TDMCP_RAG_EMBED_BATCH` (default 64, range 1–512) splits the embed set into batches per Ollama `POST /api/embed`; the one-vector-per-input cardinality guard fires per batch. - **Creative RAG — experimental LanceDB backend.** `TDMCP_RAG_BACKEND=lancedb` selects a LanceDB-backed index store via the **optional** `@lancedb/lancedb` dependency (not in the default install). The store factory falls back to the JSONL backend with a logged warning when the dependency is absent, so a misconfiguration never breaks `sync`/`index`. - **Creative RAG — content-type-aware binary extensions.** Downloaded binaries are saved with the extension implied by the response `Content-Type` (`.png`/`.webp`/`.gif`/`.tif`/`.svg`/`.jpg`) instead of a hardcoded `.jpg`. - **Creative RAG — versioned, migration-tolerant index lines.** JSONL index lines are tagged with an `indexVersion`; legacy (untagged) lines are migrated forward on read instead of being dropped, and future-versioned lines are skipped rather than crashing an older reader. ### Changed - Hardened the PR validation pipeline with separated quality workflows, scoped PR-run cancellation, semantic-title and changelog policy checks, and a Node engine floor aligned with the locked ESLint toolchain. ## [0.9.0] - 2026-06-10 The **hype-scout Round 4 campaign** — the complete external trend-driven backlog (`_workspace/hype-scout/HYPE_TOOL_BACKLOG.md`) shipped as a single release. Five themed waves of work are consolidated here: force multipliers, top-5 quick wins, POP combos, the generative-AI bridge wave (including the `create_ai_mirror` capstone), and the optional VFX aesthetic tail. **28 new tools**, all live-verified against TD 099 build 2025.32820 / bridge 0.6.1. ### Added — Hermes AI party POC - **`tdmcp-agent ai-party`** — dry-runs a Telegram/Hermes-style show-control message through the existing AI Show Director policy runtime without creating a TouchDesigner context or touching hardware. - **`tdmcp-agent ai-party telegram-once`** — processes one Telegram Bot API long-poll batch (`getUpdates` with message/callback updates), maps messages to bounded `ShowIntent`s, and replies with `sendMessage` status plus inline approve/deny buttons for queued effects. - **`aiPartyGateway` / `telegramShowGateway` automation modules** — deterministic Hermes fallback parsing, raw Hermes candidate validation, audience/operator ACLs, malformed-output blocking, approval queue handoff, and Telegram reply formatting for the AI-controlled-party POC. ### Added — Live Nervous System AI Party rehearsal POC - **`src/automation/aiPartyLive/`** — local dashboard/backend for the AI Party rehearsal loop: operator text, optional Ollama parsing, deterministic fallback parsing, policy decisions, approval queue, JSONL audit log, WebSocket dashboard snapshots, panic-safe handling and TouchDesigner health/preview endpoints. - **`npm run ai-party:dev` / `dry` / `td-build` / `test` / `telegram`** — run the local dashboard, deterministic rehearsal smoke, optional TD demo-network builder, focused POC test suite and allowlisted Telegram long-poll path. - **Simulation-first hardware boundary** — physical effects stay simulated by default; the TD builder creates `sim_dmx_table` and `dmx_out_disabled`, not a venue-ready DMX output. ### Changed — Package distribution - **npm package publishing** — `@dpantani/tdmcp` remains the public npm package identity for `0.9.0`, with explicit public scoped publishing. Runtime version detection also accepts the unscoped `tdmcp` name so local/dev metadata cannot fall back to `0.0.0`. ### Added — Force multipliers (D.0) - **`create_external_io` outbound modes** — new `ndi_out` and `syphon_spout_out` modes (Layer 2). KB-confirmed stock TOPs (`ndioutTOP`, `syphonspoutoutTOP`). The universal "push a TOP out to StreamDiffusion / ComfyUI / MediaPipe-Spout-loopback" plumbing. - **`dropExternalTox` helper** (`src/tools/util/dropExternalTox.ts`) — standardizes the dotsimulate TOX-drop pattern. Internal helper; consumed by every Wave-4 wrapper. - **`build_pop_chain`** — Layer-2 builder for ordered POP chains over the 77-kind curated subset of TouchDesigner's new point-operator family. Safe-default params per POP type sourced from the knowledge base; fail-forward warnings; `extra_inputs` with special-cased par binding for the lookup family (`lookup_texture_pop` → `par.top`, `lookup_channel_pop` → `par.chop`). ### Added — Top-5 quick wins (D.1) - **`create_pose_controlnet_driver`** (Layer 1) — OpenPose-color skeleton renderer over the existing `createPoseTracking` / `createPoseSkeleton` pose stack. ControlNet-ready RGB TOP; optional `output_mode: "syphon_spout" | "ndi"` routing through the FM-01 outbound modes. - **`create_ascii_render`** (Layer 1) — character-grid TOP, sibling of `create_dither` / `create_halftone`. Three color modes (`mono` / `source-color` / `two-color`), default phosphor-green; configurable charset and cell size. - **`create_phrase_locked_cue_engine`** (Layer 1) — extension over `createSyncExternalClock`: quantizes cue triggers to the next musical phrase boundary (1/2/4/8/16/32/64 bars). Two quantize modes (`next` / `aligned`), FIFO queue, local Beat CHOP so it composes without a tight upstream binding. - **`create_audio_glsl_uniforms`** (Layer 2 helper) — binds named audio CHOP channels to a target `glslTOP`'s `seq.vec` uniform slots via Python expressions. Reuses the `createGlslShader` seq.vec precedent. ### Added — POP combos (D.3) - **`create_pop_particle_system`** (Layer 1) — 4-stage POP particle system (particle → feedback → lookup_texture force → field). - **`create_pop_growth`** (Layer 1) — POP-native reaction-diffusion / growth presets, three modes (`dendritic` / `coral` / `lichen`). - **`create_pop_lines_pointcloud`** (Layer 1) — plexus-style line web via `neighbor_pop` + downstream Script SOP line emission. - **`create_depth_pop_field`** (Layer 1) — depth-driven POP scatter with explicit depth path or auto-spin `setup_segmentation` (MediaPipe). - **`create_stipple_pointcloud`** (Layer 1) — density-from-luminance stipple via `lookup_texture_pop`; `bw_dots` / `colored_dots` / `random_jitter` modes. ### Added — Generative-AI bridge wave (D.2) - **`drive_streamdiffusion`** — dotsimulate StreamDiffusionTD .tox wrapper via the `dropExternalTox` helper; FM-01 outbound binding; synthetic noiseTOP source fallback. - **`setup_mediapipe_plugin`** — torinmb mediapipe-touchdesigner canonical .tox EXTENSION over the stock `setup_*_tracking` family. - **`create_depth_from_2d`** — TDDepthAnything v2 wrapper; RGB-in → depth-TOP-out. - **`create_gaussian_splat_scene`** — Anglerfish-graphics TDGS .tox wrapper (top trend of Round 4, 4-surface unanimous H). - **`create_ai_mirror`** — **CAMPAIGN CAPSTONE** COMBO recipe: camera input → `drive_streamdiffusion` → output binding → control panel. Three source modes (synthetic/camera/existing_top), three output paths (internal/syphon/ndi). Graceful degradation when SD's .tox isn't installed: builds the full skeleton anyway and surfaces the SD friendly message as a warning. - **`connect_comfyui`** — ComfyUI bridge (Layer 2). Two modes: `tox_drop` (olegchomp/TDComfyUI or JiSenHua/ComfyUI-TD .tox) and `webclient` (stock webclientDAT POST + workflow JSON). - **`connect_daydream_cloud`** — Daydream Cloud-hosted StreamDiffusion (Layer 2). Skips the local GPU/CUDA gate. Env-only API key. - **`create_llm_chain`** — LLM connector (Layer 2). Two modes (`tox_drop` dotsimulate LOPs or `webclient` OpenAI-compatible) and four providers (`openai` / `anthropic` / `ollama` / `custom`). All API keys are env-only — Node never touches the values. ### Added — VFX aesthetic tail (D.5) - **`create_slit_scan`** (Layer 1) — time-slice slit-scan render via cacheTOP, sibling of `create_time_echo`. - **`create_chrome_blobs`** (Layer 1) — liquid-chrome / metaball preset stack (noise → blur → threshold → glslTOP chrome env → composite). - **`create_vintage_lens`** (Layer 1, extension over `applyPostProcessing`) — lens / CA / vignette preset. - **`create_reaction_diffusion`** (Layer 1) — Gray-Scott RD wrapper over the shipped `recipes/reaction_diffusion.json`. Canonical `seq.vec` uniform binding pattern; LUT palette chain wrapped in fail-forward so the RD core ships even if rampTOP par naming varies. - **`create_pixel_sort`** (Layer 1) — threshold pixel-sort glslTOP. - **`create_volumetric_field`** (Layer 1) — 3D-texture feedback stack (multiple 2D slices via cacheTOP + glslTOP stack walker with Beer-Lambert alpha accumulation). Explicitly **not** a raymarcher. Six baked palettes. - **`create_voxel_stack`** (Layer 1) — isometric voxel-stack render rig with `mergeCHOP` instance-channel combiner. - **`create_facade_mapping`** (Layer 1) — multi-projector blend skeleton; per-projector brightness exposed. ### Improved — FM-02 hardening + bridge installer layout - **TS-side `toxCandidatePrecheck` helper** (`src/tools/util/toxCandidatePrecheck.ts`) — when all candidate `.tox` paths are absolute AND none exist on disk, every wrapper short-circuits with a friendly error in milliseconds with **NO bridge call**. Closes the entire class of "TD hangs when the user doesn't have the .tox installed" bugs that surfaced during the AI-bridge wave's live QA. Project-relative candidate defaults were stripped from `drive_streamdiffusion`, `create_gaussian_splat_scene`, `connect_comfyui`, and `create_llm_chain` so the precheck always short-circuits when nothing is installed. - **`dropExternalTox` fail-fast** — incomplete bridge reports (missing `found_path` / `container_path`) now return a friendly error instead of being silently coerced to `{ok: ...}` with empty paths. - **Bridge installer node layout** (`td/modules/mcp/install.py`) — the installed bridge COMP's inner nodes (`callbacks`, `webserver`, `webserver_callbacks`, `events_hook`, `error_log`, `error_log_callbacks`) are now positioned in a fixed, legible arrangement instead of stacking at the origin. ### Fixed (rolled up across the campaign) - `build_pop_chain` `extra_inputs` wiring no longer raises `IndexError` on `lookup_texture_pop` / `lookup_channel_pop`. These fixed-arity POPs take their secondary source via a par reference (`par.top` / `par.chop`), not an input connector. - `build_pop_chain` payload script uses `.get()` defaults for `defaults_map` and `unverified_note` — direct low-level callers no longer crash with `KeyError`. - `drive_streamdiffusion` synthetic source fallback: noiseTOP when `source_top_path` is absent (was a bare moviefileinTOP that prompted a macOS file-chooser modal → TD hang). - `create_ai_mirror` graceful-degradation path when SD `.tox` is missing: build the full skeleton + control panel, surface the SD friendly error as a warning. Slider COMPs are now initialized from `args.strength` / `args.cfg` before `.expr` bindings are applied (was drifting from caller-specified values). Precheck-missing detector narrowed to `\bno_candidate_found\b` to avoid masking unrelated errors. - `create_llm_chain` — Python escape: `"# prompt mirror\n"` / `"# response mirror\n"` were emitting real LF characters and unterminating the Python string literal; the escape is now double-backslashed. TD optype `datExecuteDAT` (camelCase) → the actual `datexecuteDAT`. webclientDAT par names corrected (`requestmethod` → `reqmethod`; dropped non-existent `asynchronous` / headers DAT par / request data DAT par writes — webclientDAT is async by default via its callbacks and body content goes through the body_builder textDAT). - `create_stipple_pointcloud` geometryCOMP par names corrected against TD 099 (`pointcloudpop` → `instancepop`; `pointsize` → `instancesx/y/z` scale as the dot-size proxy). - `create_pop_particle_system` — prepend a `point_generator_pop` seed before `particle_pop` to satisfy its required emitter input (clears the "Not enough sources" cook warning). Now also stops on `chainResult.isError` instead of silently continuing. - `create_voxel_stack` optype casing: `topToCHOP` → `toptoCHOP`. Multiple `connect(*, nullCHOP)` calls replaced with a `mergeCHOP` combiner so all instance channels (tx / tz / ty / sy / colorTop) reach the instancing path together. - `create_reaction_diffusion` — container_path is threaded through the overlay payload from `buildFromRecipe`'s actual container instead of being reconstructed from `args.name` (recipe-id-derived names differ from caller-supplied names). GLSL uniform binding now uses the canonical `seq.vec.numBlocks + setattr(g.par, 'vecname', ...)` pattern (mirrors `createGlslShader.ts` L115-117). rampTOP LUT key-par setting wrapped in fail-forward try/except. - `create_slit_scan` — `_g.par.seq.vec.numBlocks` → `_g.seq.vec.numBlocks` (the `seq` property is on the operator, not via `par`). - `create_facade_mapping` — missing `await` on `builder.add` in the `existing_top` source-mode branch. - `create_depth_from_2d` — `executePythonScript` second argument is now `true` so the success-path bridge response carries stdout for `parsePythonReport`. - `create_phrase_locked_cue_engine` — `parameterexecuteDAT "flush_exec"` is now bound to the container via `op: builder.containerPath` + `pars: "Flush"` so it actually receives the Flush parameter pulses. - `create_pixel_sort` — Iterations control `type` corrected from `"float"` to `"int"` to match the schema. - `drive_streamdiffusion` schema description corrected — the `source_top_path` is a filesystem video/image file path (used to set `moviefileinTOP.file`), not a TouchDesigner operator path. ### Verified All 28 features were live-cooked against TD 099 build 2025.32820 / bridge 0.6.1 at release time. Offline gates: typecheck + build + biome + vitest (3946 pass) + validate:recipes (32) + test:bridge (196). ### Added - **AI-Controlled Party producer POC runner** — `tdmcp-agent ai-party-poc` runs the closed-rehearsal proof in dry-run/simulated mode: text/transcript fan-in, `ShowIntent` policy decisions, approval queue state, audit log, optional auto-approval into simulated effect events, and zero hardware plans. Fixtures live under `tests/fixtures/show-director/` and are pinned by `tests/unit/showDirectorFixtures.test.ts`. ## [0.8.3] - 2026-06-03 ### Fixed - **`create_histogram_scope`** — geometry now renders a proper distribution curve instead of a stray hairline at the far left. The `choptoSOP` was fed only a `ty` channel, so TD warned `Channel "tx"/"tz" not found` and collapsed every point to x=0. The build now synthesises `tx` (Pattern CHOP ramp -1..+1 over `bins` samples) and `tz` (Pattern CHOP constant 0) and merges them with the existing `ty` via a Merge CHOP. The shader also normalises counts by the total tap count so heights stay inside the orthographic camera's Y range. - **`create_control_panel`** — an `rgb` control with exactly 3 `bind_to` targets now actually drives those parameters (each component → one target) instead of dropping the binding with a warning. Restores live `TraceColor` reactivity for `create_histogram_scope` and other scopes. - **`setup_face_tracking` / `setup_hand_tracking` / `setup_segmentation`** — robust JSON DAT / mask TOP lookup. The torinmb mediapipe-touchdesigner engine has renamed its outputs across versions (e.g. `face` → `face_landmarks` → `face_landmark_results`); the tools now probe a priority-ordered candidate list and fall back to a regex scan so a future rename does not silently break setup. ### 2026-06-02 — Wave 12 (live-show resilience + LLM token budget + CLI ergonomics) #### Added - **`create_safety_blackout_chain` (Layer 1)** — single-toggle kill / dimmer chain for live shows: master `mathCHOP` (mult), pre-output `levelTOP` (opacity), and panic CHOP exposed as one control. ALLOW_EXEC=0 safe — composes via existing structured tools, no raw Python. CLI: `tdmcp-agent layer1 safety_blackout_chain`. - **`create_setlist_runner` (Layer 1)** — declarative setlist sequencer wrapping `timerCHOP` + index switch + cue table for show-time scene advancement with hold/loop/jump controls. CLI: `tdmcp-agent layer1 setlist_runner`. (Live UNVERIFIED: Timer CHOP `cycle` writability.) - **`create_show_failover` (Layer 1)** — A/B render-path failover with `lookupCHOP` health routing and automatic switch on cook errors; survives a single-source failure mid-show. CLI: `tdmcp-agent layer1 show_failover`. (Live UNVERIFIED: Lookup CHOP table format.) - **`create_pose_reactive` (Layer 1)** — closes ROADMAP A.6: body-skeleton-driven reactive network (pose landmarks → analyze → modulation bus) usable with the MediaPipe TD plugin or any landmark CHOP source. CLI: `tdmcp-agent layer1 pose_reactive`. - **`auto_repair_loop` (Layer 2)** — driver that scans `get_td_node_errors`, applies safe known-good fixes (param resets, reconnects), and reports a structured repair log. CLI: `tdmcp-agent layer2 auto_repair_loop`. (Live UNVERIFIED: Lookup CHOP table format used for routing.) - **`compact_graph_digest` (Layer 3) + `tdmcp://digest/{path}` resource** — token-bounded structural digest of a TD subtree (families, fan-in/out, cook hotspots) usable by the basic-tier local-LLM copilot as a first-choice inspection tool. CLI: `tdmcp-agent digest `. Now registered in `LLM_TOOLS` (basic tier). (Live UNVERIFIED: Info CHOP `total_cooks` channel name.) - **`scaffold_recipe_from_network` (vault tool)** — inverse of `apply_recipe`: serialize an existing TD subtree into a `RecipeSchema`-valid JSON template (nodes, connections, exposed controls) and write it into the vault. CLI: `tdmcp-agent vault scaffold_recipe_from_network`. - **`POST /api/param_modes/batch` bridge endpoint + `readParameterModesBatch` client** — typed batch read of parameter expression/bind/export modes for many nodes in one round-trip (Zod-validated envelope). Replaces N-way `exec`-loop pattern; falls back to exec on older bridges. - **`tdmcp init` CLI** — `tdmcp init [--dry-run] [--yes] [--json]` first-run scaffold for artists: writes a sensible `tdmcp.config.json`, suggests a profile, and prints next-step doctor hints. - **`tdmcp ask` CLI** — `tdmcp ask ""` thin shell over the local-LLM copilot (basic-tier tool subset, including the new `compact_graph_digest`) for one-shot questions without launching a chat loop. #### Changed - **`create_audio_reactive` — opt-in transient gate + sidechain duck modulation bus.** New flags `transient_gate`, `transient_threshold`, `transient_hold_ms`, `sidechain_duck`, `duck_depth`, `duck_release_ms` add a `transient` `analyzeCHOP` (function=8), `transient_hold` / `duck_env` `filterCHOP`s, a `duck` `mathCHOP`, and merge into a `mod1` `nullCHOP` modulation bus that downstream tools can `bind_to_channel`. **Backward-compat:** all defaults preserve the prior byte-identical container; existing tests, recipes, and CLI callers omitting the new fields keep working (impl now re-parses `z.input` internally). When `expose_controls=true`, the four new knobs (Transient Threshold, Transient Hold (ms), Duck Depth, Duck Release (ms)) appear on the controls panel. (Live UNVERIFIED: transient detector operator type, Filter CHOP ramp-unit semantics.) - **`set_perform_mode` — promoted to typed `POST /api/perform` REST endpoint** with Zod-validated `performMode` snapshot in the response. Exec fallback preserved for older bridges. (Live UNVERIFIED: `project.performMode` writability via the new endpoint.) #### Internal - **`familyOf(type)` lifted to `src/resources/familyOf.ts`** — shared helper now imported by both `sceneSummary.ts` and the new `graphDigest.ts` resource; removes a hand-duplicated copy and keeps family-classification logic single-sourced. #### Notes QA report `_workspace/04_qa_wave12.md` — all four PR gates green (typecheck, build, biome, vitest 3690 tests), recipes 31/31 valid, bridge tests 182 pass, cross-boundary coherence PASS. Four live-only items remain UNVERIFIED-pending-bridge (Lookup CHOP table format; Timer CHOP `cycle` writability; Info CHOP `total_cooks` channel name; `project.performMode` writability) — to be probed in a live TD session before the next tagged release. ## [0.8.2] - 2026-06-02 ### Added - **First-party recipe `audio_reactive_basic`** (8 nodes, 6 connections, 2 exposed controls) — minimal audio-in → analyze pattern from `create_audio_reactive`: `audiodeviceinCHOP` fans out to an `audiospectrumCHOP` (outlength 256) and an `analyzeCHOP` RMS, with a `nullCHOP` for stable downstream `bind_to_channel` and a `choptoTOP` + `levelTOP` Sensitivity stage publishing the spectrum texture. A `constantTOP` placeholder is wired to `nullTOP` out and ready for the artist to bind its colorr expression to `op('level_null')['chan1']`. Offline-validated against `RecipeSchema`; live cook-check pending (UNVERIFIED). - **First-party recipe `keyframe_animation_basic`** (5 nodes, 3 connections, 2 exposed controls) — Animation COMP showcase paralleling `create_keyframe_animation`: `animationCOMP` (artist authors 2 channels `tx`/`ty` with 5 keys each in the Animation Editor) feeds a `speedCHOP` for global playback rate, wrapped by a `nullCHOP` for stable channel refs, with a `constantTOP` target ready for `op('anim_null')['tx']`-style expressions. Foundation for declarative camera/object motion. Manual-wire documented inline. Offline-validated against `RecipeSchema`; live cook-check pending (UNVERIFIED). Total: 31/31 recipes valid. - **First-party recipe `pose_skeleton_standalone`** (8 nodes, 1 connection, 1 exposed control) — placeholder skeleton renderer for `create_pose_skeleton` with a built-in Table DAT of 8 static landmarks (head/shoulders/hips/hands/ feet) feeding a Script SOP that draws joints + bones through a `lineMAT`, rendered via `geometryCOMP` + `cameraCOMP` + `renderTOP`. Foundation for any custom pose source (Kinect, OSC, file playback) without depending on the torinmb MediaPipe plugin. Offline-validated against `RecipeSchema` via `npm run validate:recipes`; live cook-check pending (UNVERIFIED). - **First-party recipe `particle_system_basic`** (8 nodes, 1 connection, 3 exposed controls) — foundational `create_particle_system` template: an 8×8 `gridSOP` emitter feeds a `particleSOP` with a constant force CHOP for gentle vertical drift, rendered through `pointspriteMAT` + `cameraCOMP` + `lightCOMP` + `renderTOP`. Live controls expose BirthRate, Lifetime, and ForceY. Offline-validated against `RecipeSchema`; live cook-check pending (UNVERIFIED). Total: 29/29 recipes valid. - **First-party recipe `feedback_network_basic`** (6 nodes, 6 connections, 2 exposed controls) — minimal recursive feedback pattern (noise seed → `compositeTOP` operand=maximum + `feedbackTOP` → `blurTOP` → `levelTOP` brightness1 decay → `nullTOP`), the standalone showcase of `create_feedback_network`. Offline-validated against `RecipeSchema` via `npm run validate:recipes`; live cook-check pending. - **First-party recipe `glsl_shader_basic`** (2 nodes, 1 connection, 4 GLSL uniforms exposed as controls) — single `glslTOP` with inline plasma fragment shader mixing layered sines across a two-color gradient (`uTime`, `uScale`, `uColorA`, `uColorB`), the showcase of `create_glsl_shader`. `uTime` needs a one-line manual binding to `absTime.seconds * speed` after import (schema parameters take constants only). Offline-validated against `RecipeSchema`; live cook-check pending. - **First-party recipe `kinetic_text_audio_reactive`** (7 nodes, 5 connections) wiring `text` → `transform` → `level` → `out` alongside an audio band-split chain (`audioin` → `bass` → `analyze1`). Recipe delivers the nodes + connections offline-valid; the final audio→brightness binding is manual after import (set `level1.brightness1` to expression `op('analyze1')['chan1']*pulse_gain`), since `RecipeSchema` parameters only accept constant values. Offline-validated against `RecipeSchema` via `npm run validate:recipes`; live cook-check pending. - **First-party recipe `decks_layer_mixer`** (6 nodes, 5 connections, 2 exposed controls) — two decks with per-deck gain summed through a composite mixer, the schema pattern shared by `create_decks` + `create_layer_mixer`. Offline-validated; live cook-check pending. - **First-party recipe `depth_displacement_post`** — synthetic depth map warps a ramp source through a Displace TOP, then a post stack (blur + level grade) finishes it; runs with zero hardware. Offline-validated; live cook-check pending. - **First-party recipe `kinetic_text_path_follow`** — manual-wiring template for kinetic text following a deterministic circular path driven by two sin/cos LFO CHOPs (placeholder for a future native path-follow extension). Offline-validated; live cook-check pending. - **First-party recipe `optical_flow_particles`** — live video drives an optical-flow vector field that pushes a GPU particle system, producing motion-reactive trails. Offline-validated; live cook-check pending. - **First-party recipe `mediapipe_face_overlay`** (11 nodes, 5 connections, 5 exposed controls) — manual-wire template that mirrors what `setup_face_tracking` (v0.8.1) builds: a webcam background dimmed via `levelTOP`, a `selectCHOP` pointed at the MediaPipe face-adapter CHOP driving an instanced dot SOP through a `geometryCOMP` + `renderTOP`, composited over the camera with a final tint. Offline-validated against `RecipeSchema`; live cook-check pending. - **First-party recipe `scene_timeline_demo`** (9 nodes, 6 connections, 4 exposed controls) — declarative show-clock demo mirroring the `create_scene_timeline` Layer-1 orchestrator: a `timerCHOP` playhead + null + segments `tableDAT` driving three scenes (noise / radial ramp / violet hold) blended through chained `crossTOP`s with play/rate/fade knobs. Offline-validated; live cook-check pending. Recipe count: 15 → 22. - **First-party recipe `scene_3d_basic`** (6 nodes, 1 connection, 3 exposed controls) — foundational `create_3d_scene` template: `geometryCOMP` holding a `sphereSOP` (render+display flagged) + `cameraCOMP` (tz=5) + `lightCOMP` + `renderTOP` → `nullTOP`. Starting-point for 3D visuals; bind RotateY to a tempo ramp or audio feature manually after import (`RecipeSchema` parameters take constants only). Offline-validated against `RecipeSchema`; live cook-check pending. - **First-party recipe `video_synth_oscillator`** (2 nodes, 1 connection, 5 GLSL uniforms) — procedural Lissajous oscillator color synth mirroring `create_video_synth` lissajous mode: a `glslTOP` (1280×720) drawing two sine oscillators as a glowing curve with `uTime` / `uScale` / `uFreqX` / `uFreqY` (vectors page) and `uColor` (colors page) uniforms exposed via `glsl_uniforms`. Bind `uTime` to `absTime.seconds * Speed` manually after import to animate. Offline-validated; live cook-check pending. - **First-party recipe `kinetic_text_standalone`** (5 nodes, 3 connections, 4 exposed controls) — text-only showcase of `create_kinetic_text` styles without audio binding: `textTOP` → `transformTOP` (scale pulse) → `levelTOP` (opacity fade) → `nullTOP`, with a sine `lfoCHOP` wired in as the breathing driver. Bind `sx`/`sy` and `opacity` to LFO expressions manually after import. Offline-validated; live cook-check pending. Recipe count: 22 → 25. - **`repair_network` snapshot + rollback.** The repair loop now captures `(par.path, par.mode)` and `(op.path, op.bypass, op.display)` before each applied step. After the post-repair error recheck, if `errors_after >= errors_before` and the run is not a dry-run, the snapshot is restored in reverse order, applied steps are marked `reverted: true`, and the report carries a new `rolled_back: true` flag with a "rolled back" line in the summary text. Old reports without the flag remain compatible. - **New bridge endpoint `POST /api/transport`** for timeline control (play / pause / seek / cue / rate). Lives in `td/modules/mcp/services/transport_service.py` with controller wiring in `td/modules/mcp/controllers/api_controller.py`. Not gated by `TDMCP_BRIDGE_ALLOW_EXEC` — works on a hardened bridge. Client-side envelope is `TransportStateSchema` in `src/td-client/validators.ts` and `client.controlTimelineTransport(...)` in `src/td-client/touchDesignerClient.ts`. Bridge Python tests: +13 (`test_transport_service.py` covers play/pause/seek-clamp/cue known/cue absent/rate/error paths; `test_api_controller.py` adds dispatch + missing-action tests). ### Changed - **Release workflow keeps npm manual by default.** Tag pushes still run the release gates, build/upload `tdmcp.mcpb`, and create the GitHub Release. npm publish now requires both `TDMCP_AUTO_NPM_PUBLISH=true` and `NPM_TOKEN`, so the normal 0.8.2 handoff can keep npm / mcp-publisher as manual follow-up steps. - **`control_timeline_transport` now prefers the REST endpoint.** The tool now calls `client.controlTimelineTransport(...)` via `tryEndpoint`, falling back to `executePythonScript` only on endpoint miss. Output shape preserved; existing callers unaffected. Bridge promotion wave-2 (G4 / v1.0 Consolidation). - **Coverage gate bumped: `functions: 77 → 80`** in `vitest.config.ts`. Wave-3 measured Fn 83.60% globally (margin > 3pp); other thresholds (statements 84 / branches 70 / lines 85) kept at current values pending coverage wave-4 on the CLI surface (`src/cli/agent.ts`, `src/cli/tui.ts`). - **`snapshot_td_graph` prefers REST endpoint for parameter modes.** When `include_modes: true`, the tool now calls `client.readParameterModes` via the `tryEndpoint` REST-first / exec-fallback pattern instead of going through `executePythonScript` directly. The output shape is preserved (normalized via `normalizeParameterModes`), so existing callers are unaffected. Bridge promotion wave-1 (G4 / v1.0 Consolidation). ### Fixed - **`detect_pitch` notes/threshold consistency:** the user-facing `notes` string now advertises the actual hard-coded `DEFAULT_THRESHOLD = 0.0005` instead of the stale `0.02`. The gate magnitude was already correct; this fixes the "near-zero default threshold" symptom from the v1.0 honesty pass by reconciling the docstring (not the constant). ### Tests - **`tests/unit/detectPitch.test.ts`** — pinned that `gate.boundmin` and the exposed `Threshold` knob default share the same magnitude (`0.0005`), and pinned that the user-facing `notes` string matches that magnitude (the earlier `it.fails` marker is now a regular green `it(...)`, removed once the docstring was reconciled). - **`tests/unit/createEnvelopeFollower.test.ts`** — added a sidechain routing topology assertion: in `mode: "duck"`, the generated Python script wires source → select → lag → invert → clamp → null, binds the configured target's parameter to the duck output via an `op(...)[...]` expression (using a robust `rfind('.')` split so paths with dots work), and sets the target parameter mode to `EXPRESSION`. - **`tests/unit/vaultRoundTrip.test.ts`** (new) — proves the vault-codec round-trip (`recipeToMarkdown` ↔ `recipeFromMarkdown`) is deterministic and fixed-point under real filesystem `Vault.write` / `Vault.read`, preserves verbatim value-resolution parameters (e.g. `value: "noise1"`), and that `RecipeLibrary` reads back what we wrote. - **`tests/unit/setlistRunner.test.ts`** — coverage wave-3 added 22 new tests (17 → 39) covering `resolveStart` warnings, `quantize=bar` forwarding, scene-recipe/preset info paths, beat mode without `beatSource`, prev/goto signals with valid + invalid targets, step preemption across stop/next/prev/goto, generic `TdError` (non-connection) and non-`Error` thrown values, manual mode `elapsed` path, empty setlist, `parseSetlistInput` `.markdown` / no-filename / malformed YAML branches, and `loadCanonicalSetlist` JSON failure. - **`tests/unit/snapshotTdGraph.test.ts`** — added two assertions for the REST promotion: "prefers /api/nodes/:seg/params" (asserts exec was NOT called) and "falls back to /api/exec when the REST endpoint is missing" (asserts exec WAS called). ### Docs - Added the **Tool API contract** reference page (`docs/reference/tool-contract.md`) documenting the invariants every MCP tool follows (naming, input schema, error handling, offline behaviour, result shape, deprecation) and that will be frozen at 1.0. Linked from the EN reference sidebar. - **Roadmap honesty pass:** - Rewrote the *Experimental & needs validation* section into four honest buckets (live-music tuning, hardware round-trip pending, multimodal-LLM dependent, rollback tuning), split the signal-detection bullet, and declared `sync_external_clock` `mode='tap'` as stable. - Removed `repair_network` from the multimodal-LLM-gated bullet in *Out of scope* (its remaining hardening is offline rollback-regression testing). - Reconciled the *Planning archive*: parágrafos A.3 e A.6 now reflect that `packages_cli_help_and_completion_parity`, `no_color_flag_is_dead`, MediaPipe face/hand/segmentation and `create_strange_attractor` shipped in earlier releases; removed the duplicate Round-2 `param_changed_event` row; moved Round-3 hardware/GPU/cloud/multi-machine/paid-license rows (`create_machine_sync`, `create_depth_from_2d`, `create_sensor_input`, `create_laser_output`, `create_multitouch_surface`, `drive_diffusion_tox`, `create_lidar_reactive`, `create_volumetric_fire`, TouchEngine headless path) into *Out of scope* under explicit Round-3 bullets. - Expanded the *v1.0.0 — Consolidation* section with ready/blocked criteria per frente (tool API contract, docs & guides, coverage, recipes, bridge hardening). ## [0.8.1] - 2026-06-02 ### Added - **Persistent AI session profile is now part of the public MCP surface:** `load_session_profile` is registered with the rest of the tools, and `tdmcp://session/profile` is registered with the resources. Agents can now load the local taste/conventions/recent-work snapshot that the docs already referenced. Tool registry: 278 → 279. ### Fixed - **Artist-owned writes and package state are atomic.** Vault note writes, vault binary writes and the package registry JSON now use a write-temp-then- rename helper that preserves existing file permissions and cleans up failed temp files. Package installs now extract into a sibling incoming directory and only replace the staged install after a successful extract, so transient download or extraction failures no longer destroy the previous working copy. - **HTTP transport startup fails cleanly.** `tdmcp serve --http` now rejects `listen()` errors such as `EADDRINUSE` instead of surfacing them as unhandled process-crashing events; it also closes the event stream on listen failure and closes per-session MCP servers when an initialize request fails before session registration completes. - **Bridge fallback policy is centralized.** New `tryEndpoint()` keeps the endpoint-first / exec-fallback behavior for older TouchDesigner bridges, while still surfacing validation errors, connection failures and unrelated throws unchanged. `read_parameter_modes`, `set_dat_content`, `edit_dat_content` and `disconnect_nodes` now share that tested helper. - **Transient GET retries cover bridge 5xx API errors.** Read-only bridge requests now retry `TdApiError` responses with status >= 500, matching the existing transient retry policy without retrying side-effecting POSTs. ### Changed - `KnowledgeBase.searchOperators` caches per-operator search haystacks, the cookbook resource caches successful EN/PT reads, and the server defers the synchronous warmup log so transports can begin accepting connections sooner. ## [0.8.0] - 2026-06-02 ### Added - **AI Show Director (dry-run policy layer):** an MCP-level policy wrapper that evaluates show-directing tool calls in dry-run mode before execution, returning the planned action + rationale so artists can preview an AI-driven set without the bridge touching the network. Backed by `tests/unit/showDirector.test.ts`. - **Top-level CLI completion/package parity:** `tdmcp completion ` now prints a static completion snippet for the primary binary, including the package-manager shortcuts (`search`, `list`, `info`, `install`, `uninstall`, `doctor`, and `packages path`) and their common flags. `tdmcp --help` now also lists those package subcommands directly instead of hiding them behind one summary row, and `tdmcp packages --help` prints package-manager usage instead of failing parse. - **Expanded `tdmcp-agent doctor --fix` repairs:** `doctor --fix` now creates a missing configured `TDMCP_VAULT_PATH`, scaffolds the default profile directory, writes a missing `TDMCP_BRIDGE_TOKEN` to `.env` with owner-only permissions, and can run `install-bridge --verify` behind a bounded repair hook while continuing to surface suggestions for checks that still need manual action. - **Run-file flag propagation:** `tdmcp-agent run` now carries `--no-color` through to nested JSON/stdin command steps, and run-file steps can also set `"no_color": true`. - **Bridge watch-build hot reload:** `tdmcp-agent watch-build` now treats edits under `td/` as bridge-runtime changes: after a passing typecheck/build it runs `python -m py_compile` on changed `.py` files and then calls `reload_bridge`. `--no-py-compile` and `--no-reload-bridge` keep the old build-only loop when needed. - **MCP resource follow-through:** new offline resources expose `tdmcp://glsl-snippets`, `tdmcp://cheatsheets`, and `tdmcp://learning/touchdesigner` so agents can discover vetted shader snippets, common workflow reminders, and the `teach_touchdesigner` learning path without guessing IDs. - **N-channel `create_decks`:** the legacy A/B mixer remains compatible, and a new `decks[]` mode builds 2-8 deck rigs with per-deck gain, per-deck FX-send branches into an additive bus/return, a running Cross TOP program mix, and a hard-cut Switch TOP blended back into program with `cut_mix`. - **Portable component README:** `make_portable_tox` now writes a package `README.md` by default, documenting node inventory, custom parameters, inputs/outputs and external file references beside the `.tox` and `tdmcp-component.json`; pass `include_readme:false` for the old minimal package. - **`publish_recipe_bundle`** *(library)* — writes a local, versioned recipe publish artifact: the recipe-bundle JSON, a `tdmcp-recipe-publish.json` manifest, and a `tdmcp-checksums.json` SHA-256 manifest. Tool registry: 269 → 270. - **`create_sdf_field`** *(Layer 1)* — programmable signed-distance-field raymarcher in a single GLSL TOP. CSG tree of sphere/box/torus primitives with union/intersect/subtract + smooth blend; exposes live CameraZ/Speed/StepCount/Intensity/Rotate/ColorA/ColorB/Background controls and previews the output. Closes a Roadmap Milestone-4 deferred generator. - **`create_strange_attractor`** *(Layer 1)* — deterministic strange-attractor geometry pipeline. Script CHOP integrates a chosen ODE (Lorenz / Aizawa / Halvorsen) into a rolling ring buffer; Script SOP renders an open polyline, optional Tube SOP thickens it, then a Geometry COMP + Camera + Light + Render TOP. Time-dependent (paused timeline pauses the integrator). Closes a Roadmap Milestone-4 deferred generator. - **`create_optical_flow`** *(Layer 1)* — CPU optical-flow vector-field generator built entirely from stock TOPs (blur, monochrome, cache, composite-subtract, optional edge cross-multiply, math, feedback+level). Emits an RG-packed flow TOP (R=dx, G=dy, centred at 0.5) usable as a drop-in modulator for `create_displacement_warp`, `create_gpu_particle_field` or any TOP-driven displacement chain. Defaults to TD's bundled Mosaic.mp4 clip so it builds standalone (avoids the macOS camera permission modal). Closes a Roadmap Milestone-4 deferred generator (no CUDA path required). - **`create_histogram_scope`** *(Layer 1)* — luminance + optional per-channel RGB video histogram. GPU GLSL TOP bins → CHOP normalisation → `choptoSOP` → render TOP, output is a Null TOP ready for previews or `bind_to_channel`. Closes the Roadmap Milestone-2 histogram-scope panel as a focused tool. - **`setup_face_tracking`** *(Layer 2)* — one-shot MediaPipe face-landmark tracking adapter on the in-tree tracking engine. Loads the MediaPipe ENGINE, starts the timeline and builds an adapter Script CHOP that emits a 468-sample (478 with iris) face-landmark CHOP (tx/ty/tz/confidence, centred on nose tip), ready for `bind_to_channel` and `create_data_visualization`. - **`setup_hand_tracking`** *(Layer 2)* — one-shot MediaPipe hand-tracking adapter sharing the same engine as `setup_body_tracking`. Locates the engine's hand JSON DAT and converts it into a canonical `max_hands×21`-landmark CHOP (tx/ty/tz/confidence/handedness). Recommends `coordinate_space='world'` for gesture detection. - **`setup_segmentation`** *(Layer 2)* — one-shot MediaPipe selfie-segmentation adapter on the in-tree engine. Reuses the staged `MediaPipe.tox`, enables selfie-segmentation, and publishes a clean alpha mask `Null TOP` (+ optional pre-keyed RGBA `person_rgba` Null TOP = camera × mask) ready for `create_keyer`, `create_depth_silhouette`, or any matte-consuming chain. Closes the Milestone-4 MediaPipe segmentation slot alongside face/hand tracking. - **Pluggable `doctor --fix` test hooks** — `RunDoctorOptions` exposes override hooks (`envFilePath`, `envFileWrite`, `profileDirPath`, `profileDirRepair`, `runInstallBridge`) plus `checkBridgeToken`, so the safe repair paths above are covered without touching the real user environment. - **`get_inline_preview`** *(Layer 3)* — one-shot inline inspection snapshot of any TOP: bounded thumbnail (default 256×256, capped at 1024) plus resolution / pixel-format / cook metadata and post-cook node errors, returned in a single structured payload so agents can verify a build without juggling `get_preview` + `get_td_node_errors`. Closes the Roadmap Milestone-4 inline preview pass. Tool registry: 277 → 278. - **`create_stage_dashboard` v2 layout** — opt-in `layout:"v2"` adds a stereo VU pair, a BPM readout fed by an optional `tempo_channel` (e.g. a `detect_tempo` Null CHOP), an FPS / cook-time / frame overlay, a cue timeline strip driven by an optional `cue_times[]` array (pairs from `compose_cue_list`), and a sticky confirm-tap PANIC bar. The default `layout:"v1"` keeps the original dashboard byte-for-byte. Closes the Roadmap Milestone-4 front-of-house dashboard pass. - **`generate_readme` component-doc polish** — adds `include_mermaid:true` to embed a Mermaid flowchart of the operator graph in the "Data flow" section, and a `max_nodes` cap (default 200) that truncates the Child inventory table with a one-line "_N more nodes not shown_" footer so large components produce scannable READMEs. Together with the existing `make_portable_tox` package README, this closes the Roadmap Milestone-3 "stronger component docs" item. Tool registry: 270 → 278 (eight new tools above). ### Changed - Prompt cookbook expanded with additional visual examples (EN + PT) covering tools shipped post-0.7.1, keeping `tdmcp://cookbook` aligned with the live registry. ### Security - Reduced SafeSkill prompt-injection score by removing literal system option keys from public tool descriptions (no behavior change for callers). ## [0.7.1] - 2026-06-01 ### Added - **CLI/operator DX follow-through:** `tdmcp --help` now prints top-level usage without starting the MCP server; `tdmcp-agent run -` reads run-file JSON from stdin; `tdmcp-agent run --continue-on-error` executes the remaining steps and returns the first non-zero status at the end; and `tdmcp-agent config profiles` / `config profile ` list and inspect saved venue profiles with secrets redacted. The same lane now also exposes `tdmcp-agent commands --json`, the matching `tdmcp://commands` resource, grouped `tdmcp-agent --help`, focused `tdmcp-agent help `, and `tdmcp install-bridge --verify` / `--wait` / `--port` bridge polling against `/api/info`. - **MCP resources:** `tdmcp://prompts` is now generated from the real prompt registry (removing manual drift), `tdmcp://recipes/search/{query}` searches the recipe catalog, and `tdmcp://cookbook` plus `tdmcp://cookbook/{en|pt}` expose the prompt cookbook as an MCP resource. The npm package now includes the EN/PT cookbook Markdown needed by that resource. - **Local copilot knobs:** `TDMCP_LLM_TIER`, `TDMCP_LLM_MAX_STEPS`, and `TDMCP_LLM_TEMPERATURE` configure the default chat tier, model/tool-loop step budget, and sampling temperature. The copilot system prompt now also includes the real registered prompt catalog from `tdmcp://prompts`, so it can guide users toward the right MCP prompt instead of relying on stale prompt names. - **Runtime telemetry:** `get_node_state_runtime` accepts `include_info_chop:true` to fail-forward sample a temporary Info CHOP and return its numeric channels under `info_chop`. - **`watch_node`** *(layer3, td-depth)* — read-only short-window sampling of one operator's runtime state, readable parameters, and CHOP channel values. Missing attributes/channels fail forward as warnings so the diagnostic loop stays useful across TD builds. Tool registry: 268 → 269. - **Roadmap CLI/DX follow-through:** `tdmcp install-client --write --path ` now deep-merges and verifies explicit client config files (JSON for Claude/Cursor, TOML for Codex); `tdmcp serve --http [--port]` starts loopback Streamable HTTP without changing bare `tdmcp` stdio defaults; `tdmcp-agent --output table|csv` renders list results for shell use; the REPL has persistent history + Tab completion; and `tdmcp-agent watch` gained `--pretty`, event counts, `--heartbeat-ms`, and exec hooks (`--on `, `--exec `, `--debounce-ms `) for reactive local scripts. - **Local copilot CLI flags:** `tdmcp chat --read-only` locks browser/API turns to the safe tool tier, `--creative` selects the creative tier with a warmer sampling preset, `--prompt ` runs a headless one-shot answer without opening the browser/server, and `--profile` / `--config` select saved configs for chat runs. - **Bridge health watchdog:** the TouchDesigner bridge now serves `GET /api/health` with state/status, timestamp, uptime, heartbeat metadata, TouchDesigner info and fail-forward optional performance metrics (cook/frame/drop/GPU fields are `null` when the current TD build does not expose them). ### Fixed - **Release/package warning cleanup:** the dependency override now keeps the nested `@bottobot/td-mcp`/Cheerio chain off the deprecated `whatwg-encoding` path, and `build:mcpb` strips dev-only overrides before the staged production install so the bundle build no longer emits the transient `mute-stream` `EBADENGINE` warning. ## [0.7.0] - 2026-06-01 ### Added (Ingest-extend Wave 3 sub-batch A) Three pure-Node library/publishing tools — no TouchDesigner bridge required. Lands the first three Milestone-3 (M3 — Smarter assistance & library publishing) features as a partial Wave 3; the remaining six Wave-3 features (TD-required) follow in a separate session. - **`tag_and_search_library`** — faceted browse + tag editing over the vault library (`/Recipes/*.md` + `/Components/*.md`). `op:"list"` enumerates every asset and its tags; `op:"search"` filters by free-text `query` and/or `tags_any` / `tags_all` set logic; `op:"tag"` edits one asset's frontmatter tags (union or replace, always preserving `'*'`-pinned user tags — same convention as `auto_tag_library_asset`). Pure vault I/O. - **`version_library_asset`** — SemVer `patch`/`minor`/`major` bumps for a vault recipe or component note, recorded in a sidecar `.versions.json` (`asset_path` + `current` + `history` list with version/bump/note/timestamp) and reflected in the note's frontmatter `version`. Pass `read_only:true` to inspect without bumping. Pre-existing frontmatter versions are captured as the history root on the first bump. - **`generative_classics_pack`** — the first canonical technique recipe pack: curated subset of 6 built-in recipes that recreate well-known generative looks (`feedback_tunnel`, `audio_spectrum_bars`, `noise_landscape`, `particle_galaxy`, `reaction_diffusion`, `webcam_glitch`). `list_only:true` (default) returns the technique cards + availability; `list_only:false` writes a portable `import_recipe_bundle`-compatible bundle JSON at `install_path` (default `recipes/generative_classics.pack.json`). Recipes pulled live from the recipe library so the pack always reflects the authoritative validated copies. Tool registry: 257 → 260. Unit tests: 2935 → 2953 (+18 new assertions across the three tools). ### Fixed (`create_data_source_http_ws` hotfix) - **`create_data_source_http_ws`** no longer fails with `TypeError: must be real number, not str` after node creation. Three layered bugs (all live-validated against TD 099 build 2025.32820): - The `dattoCHOP` menu parameters (`firstrow`, `firstcolumn`, `output`) were set with integer indices (`1/0/1`), which TD silently coerced through the menu list — landing on `'names'/'ignored'/'chanperrow'`. The latter two are wrong for this layout, so the CHOP produced zero or wrongly-named channels. Now uses the explicit menu names (`'values'/'names'/'chanperrow'`). - The sample `tableDAT` was laid out as a header-row + value-row table, which `dattoCHOP` cannot turn into one channel-per-selector. It is now transposed (one row per selector: `[name, value]`), matching the corrected datto config. The parser callback (`_parse_and_update`) was updated to emit the same shape. - The live-readout custom parameters were named `LastValue_`, which TD rejects (custom-param names must be one uppercase letter followed by lowercase letters only, no underscores). They are now `Last` (e.g. `Lasturl`, `Lastn`), and the expression explicitly calls `.eval()` on the channel so the float parameter receives a real number instead of a `Channel` object. - Live-validated against TD 099 (build 2025.32820) with two selectors over `httpbin.org/get`: the tool now returns 2 channels, 0 warnings, 0 node errors, and 4 working controls (`Active`, `Poll`, `Lasturl`, `Lastn`). The full unit test count goes from 2923 → 2935 (+12 tests, 4 new regression assertions on this tool). ### Added (Ingest-extend Wave 3 sub-batch B) Six TD-required Wave-3 features (mix of Layer-3 and vault tools), closing out the Wave-3 backlog ahead of the v0.7.0 cut. All gates pass (typecheck, build, biome, 2971 vitest tests, 15/15 recipes, 106 bridge tests). Live-validated against TD 099 build 2025.32820 (project `laser_dedo.1.toe`). - **`extract_palette`** *(layer3, ai)* — sample dominant colors from a TOP by capturing its preview PNG and running deterministic k-means on the decoded RGB pixels. Returns `{hex_colors[], swatches[{hex,rgb,weight}]}` sorted by dominance. Read-only; mechanism identical to `caption_top`. Live-validated via `get_preview` round-trip against a `constantTOP`. - **`export_sop_to_svg`** *(layer3, library)* — read a SOP's primitives via the bridge and emit an SVG document of polylines (each prim → one ``), auto-fit viewBox, configurable stroke/fill/scale/flip_y, optional `output_path` to disk. Pen-plotter / laser / print deliverable. Live-validated by extracting 40-point polyline from a probe `circleSOP` (Poly-iteration path). - **`swap_operator`** *(layer3, td-depth)* — change an op's TYPE in place, preserving name, position, input + output wires, and any parameters that exist on the new type. Fail-forward per-wire / per-param. Live-validated: swapped a `noiseTOP` → `rampTOP` while keeping 19 parameters and a downstream `nullTOP` wire (0 post-cook errors). - **`copilot_vision`** *(layer3, ai)* — route a vision query to the configured multimodal LLM with a TOP rendered as an inline image. Uses `ctx.llm.complete()` with a `MultimodalMessage` (text + image part); falls back with a friendly error pointing at `TDMCP_LLM_*` when no LLM backend is wired. Live-tuning UNVERIFIED — no multimodal LLM endpoint configured in this session; mechanism (preview capture + LLM contract) is covered by tests. - **`export_look_tox`** *(vault, library)* — save a COMP as a portable `.tox` inside `//.tox` with a sibling Markdown sidecar (id/type=look + name + tags + assets + created + source_path). The artist- publishing primitive for shareable looks. Vault-gated. Live-validated via a probe `baseCOMP.save()` (238-byte tox written). - **`tutorial_companion_pack`** *(vault, cli)* — scaffold a teaching companion for a build: snapshot the COMP's topology, capture previews of its output TOPs, write `tutorial.md` + `topology.json` + `network_snapshot.json` (a documentary snapshot — explicitly NOT a RecipeSchema-installable recipe) + `previews/*.png` into `///`. Composes existing read-only bridge calls; outputs are an editable starting point for an artist. Vault-gated. ### Added (Ingest-extend Wave 3 sub-batch C) Closes out Milestone 3's colour-finish polish (Part 2) and opens Milestone 4 (deeper authoring / operator DX) with three new tools + one CLI subcommand. All gates pass (typecheck, build, biome, 2987 vitest tests, 15/15 recipes, 106 bridge tests). Two TD-required tools live-validated against TD 099 build 2025.32820 (project `laser_dedo.1.toe`) under isolated probe containers — zero node errors after the cook, networks cleaned up. - **`create_color_wheels`** *(layer1, M3 colour-finish)* — classic lift / gamma / gain colour-grading wheels. Three tinted Level TOPs run in series (shadows via a gamma-biased Level, midtones via a neutral Level, highlights via a brightness-biased Level), each multiplying R/G/B channels (`redmult1` / `greenmult1` / `bluemult1`). A master Level TOP applies a global black-level offset, then an HSV Adjust TOP applies master saturation. Builds a new `baseCOMP` under `parent_path`; with `source_path` the upstream TOP is pulled in via a Select TOP, without one a Ramp TOP is graded so the chain previews standalone. Exposes nine per-channel float controls — LiftR/LiftG/LiftB, GammaR/GammaG/GammaB, GainR/GainG/GainB — each bound to the corresponding Level TOP `redmult1` / `greenmult1` / `bluemult1` parameter on its tier, plus master Offset (black-level) and Saturation knobs. - **`create_pop_geometry`** *(layer1, M4 authoring)* — Procedural Op Pattern geometry generator: build a SOP chain inside a Geometry COMP — primitive (`box` / `sphere` / `tube` / `torus` / `grid` / `line` / `text`) → Transform SOP (translate / rotate / scale) → optional Subdivide SOP → optional per-point Noise SOP displacement → Material SOP (Constant MAT) → Null SOP — then render through a Camera + Light + Render TOP to a Null TOP. Mirrors the `build_sop_geometry` declarative chain pattern but wraps it in a full Layer-1 render rig. Exposes RotateY, NoiseAmount and NoisePeriod controls. - **`tdmcp config init`** *(cli, M4 DX)* — new CLI subcommand: writes a starter `.env`-style config file with every `TDMCP_*` env var the server reads, sane defaults, and a one-line comment per setting. Default target is `~/.tdmcp/config.env`; pass a positional path to override. Secrets (`TDMCP_BRIDGE_TOKEN`, `TDMCP_LLM_API_KEY`) are emitted commented-out for manual setting. Refuses to clobber existing files unless `--force`; `--dry-run` prints the body without touching the filesystem. Pure Node, no TD bridge required. - **`elicit_missing_args`** *(layer3, M3 — verified shipped)* — already shipped in this branch (10 unit tests across LLM-elicit / offline / schema-feedback / long-context truncation / unknown-tool / no-server paths). Audited as part of this sub-batch; no changes needed — flipped to ✅ on the roadmap. Tool registry: 266 → 268. Unit tests: 2971 → 2987 (+16 new assertions). ### Added (Ingest-extend Waves 1-2) **Ingest-extend Wave 1 — Ecosystem on-ramp + signature looks** (campaign `ingest_extend_20260531`, Arc 5 "Ingest & extend" / ROADMAP Milestone 2, folded into the v0.7.0 line). One shared foundation module plus six new Layer-1 tools open tdmcp to the wider GLSL ecosystem (Shadertoy + ISF) and add four signature looks (fluid sim, image-to-particles, dither, JFA voronoi). ### Added (Ingest-extend Wave 1) - **`apply_glsl_top_mapping`** (foundation, new `src/tools/foundation/` directory) — shared GLSL-TOP translation layer: preamble injection, `out fragColor`, `iTime`→`absTime.seconds`/uniform, `iResolution`/`iMouse`/`iChannelN`→TOP inputs + uniform CHOP, ISF `INPUTS`→custom-page mapping. Pure Node/TS, no TD. Consumed by both importers below so they share one mapping contract. - **`import_shadertoy`** — paste a Shadertoy URL or `mainImage` source and get a translated, wired, previewable GLSL TOP. Translate-on-demand only (never stored/redistributed); offline-safe via `raw_source`. - **`import_isf_shader`** — parse ISF (`.fs`) JSON header + translate to a glslTOP with an auto-generated `add_custom_parameters` page (INPUTS → float/color/bool/event/long). Own parser, no bundled `.tox`. - **`create_fluid_sim`** — GPU 2D Navier-Stokes ink/dye/smoke simulation (advection → divergence → pressure-Jacobi → gradient-subtract → vorticity) with audio/motion/pointer force binding and Viscosity/Vorticity/Dissipation knobs. - **`image_to_particles`** — turn an image/video into a particle reconstruction that springs toward rest, with audio-driven scatter; Reorder TOP → CHOP → TOP-instancing. - **`create_dither`** — 1-bit/N-bit Bayer ordered dither + error-diffusion effect (palette size, gameboy preset). Own GLSL. - **`create_jfa_voronoi`** — Jump-Flood-Algorithm Voronoi / stained-glass generator, multipass GLSL, with three palette modes. **Ingest-extend Wave 2 — Color pipeline + show automation + stylization + 3D post** (campaign `ingest_extend_20260531`, Arc 5 "Ingest & extend" / ROADMAP Milestone 2). Eight new tools (3 Layer-1, 4 Layer-2, 1 quarantined Layer-2) plus new mode keys on `apply_post_processing` extend tdmcp into color management, performance instrumentation, Live integration, painterly stylization, and 3D post-processing. Seven tools are live-validated in TD 099; one ships flagged **experimental** with a tracked known issue. ### Added (Ingest-extend Wave 2) - **`create_video_scopes`** *(Layer 1)* — broadcast-style video monitor with waveform / RGB parade / vectorscope panels (histogram deferred — TD 099 lacks `histogramCHOP`). - **`create_chop_recorder`** *(Layer 1)* — capture-and-playback for any CHOP source; record a take, scrub or loop it back as a CHOP feed. - **`setup_tdableton`** *(Layer 1)* — Ableton Live bridge: probes for the TDAbleton Palette component first, falls back to a plain OSC In bridge so it works without the Palette installed. - **`apply_lut`** *(Layer 2)* — apply a LUT to any TOP via OCIO when available, image-based lookup for `.png`/`.cube` previews, or a parsed-`.cube` GLSL fallback. Color-management pipeline foundation. - **`create_flow_abstraction`** *(Layer 2)* — ETF→FDoG painterly flow effect (edge tangent flow + flow-based difference-of-Gaussians, Kyprianidis style). - **`create_npr_filter`** *(Layer 2)* — Kuwahara non-photorealistic filter with oil / pencil / watercolor variants; also exposes three new mode keys (`npr_oil`, `npr_pencil`, `npr_watercolor`) on `apply_post_processing`. - **`post_passes_3d`** *(Layer 2)* — SSAO / SSR / depth-of-field / motion-blur 3D post-passes for `create_3d_scene` / `create_pbr_scene` outputs. `apply_post_processing` now emits friendly redirect errors when invoked with 3D-only mode keys, pointing callers to `post_passes_3d`. ### Known issues (Ingest-extend Wave 2) - **`create_data_source_http_ws`** *(Layer 2, experimental)* — HTTP-poll + WebSocket data source. The `http_poll` path raises `TypeError: must be real number, not str` after node creation; the network still builds but the tool surfaces `status: "fatal"`. Tool is registered and discoverable. Fixed before the v0.7.0 public cut. **Wave 2 — Show automation + musical reactivity** (campaign `beyond_20260530`). Eight new Layer-1 tools and one CLI verb turn the v0.7.0 live-show foundation into a smarter, more musical conductor. Tool registry is now **213** (was 205). Three reactivity tools ship marked `[experimental]`; two control surfaces are gated `unverified_pending_hardware` (live phone + motorized-controller probes required before they leave that flag). ### Added (Wave 2) - **`compose_cue_list`** — natural language → fireable cue sequence. Uses the local LLM when configured, with a grammar fallback so it works offline. - **`create_prob_sequencer`** — Markov-chain step sequencer with beat-pointer deduplication; drives recipe / scene / cue triggers from a probability matrix. - **`create_two_way_surface`** *(unverified_pending_hardware)* — closed-loop OSC/MIDI feedback to motorized faders and lit pads, so the controller mirrors the live parameter state. - **`create_automation_lane`** — record + loop a parameter sweep on a bar phase using `beatCHOP`; turns any knob move into a reusable automation clip. - **`create_chroma_reactive`** *(experimental)* — FFT into 12 pitch-class channels, for key-aware and harmony-aware reactivity. - **`create_transient_reactive`** *(experimental)* — `analyzeCHOP` RMS plus `filterCHOP` lag to split a signal into a transient and a sustain channel. - **`create_energy_structure`** *(experimental)* — adaptive energy envelope with build / drop / breakdown edge detection, for song-structure-aware shows. - **`create_phone_gesture`** *(unverified_pending_hardware)* — IMU + multitouch from a phone over a Web Server DAT, exposed as CHOP channels. - **`scene_scheduler`** — new CLI verb `tdmcp-agent schedule `: cron-lite, DST-faithful wall-clock driver for unattended installations. **Wave 3 — Library provenance + AI dispatch + scene resource** (campaign `beyond_20260530`). Eight new tools (across library, vault, Layer-1, Layer-3) plus one new MCP resource and a strengthened prompt-eval harness. Tool registry is now **221** (was 213); resources gain a live scene-summary view. ### Added (Wave 3) - **`provenance_stamp`** — write a `.provenance.json` sidecar (sha256, source COMP path, toolchain versions, git metadata, author, tags) next to any saved artifact. Offline, no TD bridge. - **`checksum_and_verify_pack`** — compute (writes `tdmcp-checksums.json`) or verify SHA-256 manifests for tdmcp artifacts (.tox, recipes, bundles). - **`library_lineage_graph`** — scan the vault library, extract lineage frontmatter (parent_recipe, source_assets, remix_of, forked_from), and emit a graph as JSON / Mermaid / Graphviz DOT. - **`morph_pack`** — pack a `create_preset_morph` container's slots to a sha256-verified vault JSON; unpack to (re)hydrate the container. - **`learn_conventions`** — read-only sweep of a live TD subtree to extract naming/colour/topology/parameter conventions into the vault Memory notes. - **`moodboard_to_system`** — ingest 1–6 moodboard images and dispatch a matching generative system (palette + motion + generator pick via local LLM, deterministic fallback otherwise). - **`audio_fingerprint_to_visual`** — sample audio, compute a 4-feature fingerprint (tempo / centroid / onset density / dynamic range), and dispatch the matching Layer-1 generator tuned to the fingerprint. - **`score_build`** — read-only 0–100 rubric scoring of a built network (palette / motion / complexity / errors / perf) with deterministic improvement suggestions, optional LLM critique. - **resource `tdmcp://scene/{view}`** — live MCP resource exposing scene topology, operators, and errors views; `ResourceContext` now carries the TD client. - New offline `prompt_eval_harness` test that catches description-quality, rendering, and token-budget regressions across every registered prompt. ### Changed (Wave 3) - `fix_shader` prompt description expanded past the 50-char quality threshold so the harness can enforce it without a whitelist. **Wave 4 — TD-depth authoring + DX accelerators** (campaign `beyond_20260530`). Ten new MCP tools (across Layer 1/2/3 plus a new `cli` tool group) and two long-running CLI streamers, bringing the registry to **231** tools. ### Added (Wave 4) - **`create_engine_comp`** — build a load-balanced Engine COMP cluster that offloads a sub-network to worker processes for parallel cooking. - **`create_dmx_fixture_pipeline`** — build a DMX / Art-Net fixture pipeline (parameter channels → patch matrix → Art-Net Out) for lighting integration. - **`scaffold_tool_generator`** — scaffold a new tdmcp tool file + msw unit test from an inline spec; accelerates wave authoring. - **`extend_data_source_fabric`** — extend `create_data_source` with new feed adapters (websocket / sse / mqtt / file-tail / process). - **`build_chop_chain`** — assemble a typed CHOP-processing chain from a recipe of stages, with per-stage parameter validation. - **`author_script_operator`** — author a Script CHOP/TOP/SOP/DAT with validated callbacks + parameters; eliminates raw-Python ceremony. - **`profile_cook_cost`** — read-only profiler that samples per-node cook cost across N frames and ranks hot spots. - **`control_timeline_transport`** — drive TD timeline transport (play/pause/ seek/rate/range) as a structured tool instead of raw exec. - **`inspect_gpu_and_displays`** — offline-friendly host GPU + display inventory for stage prep + capability sniffing. - **`macro_recorder`** — start/stop/list/load tool-call macros to portable JSON via a process-wide `wrapHandler` hook installed at server boot. Replay ships in wave 5 as `run_macro_script`. - **`tdmcp-agent watch-build`** — long-running dev-loop CLI (chokidar-based) that re-runs `tsc --noEmit` + `tsup` on debounced changes under `src/` and `td/`. - **`tdmcp-agent soundcheck-monitor`** — long-running audio-features poller that emits rolling-window RMS/peak/silence alert events (ndjson on stdout). - Adds `chokidar ^4.0.3` as a devDependency for the watch-build streamer. **Wave 5 — Final P2 tail: library trust + CLI/remote ergonomics + AI copilot polish + TD-depth long-tail** (campaign `beyond_20260530`). Thirteen new MCP tools (Layer 1/2/3, library, vault, cli group) plus six long-running CLI streamers/dispatchers, bringing the registry to **245** tools. Closes out the BEYOND backlog. ### Added (Wave 5) - **`curated_collection_pack`** — bundle a curated set of vault/library assets into a verifiable, checksummed pack with provenance metadata. - **`component_changelog_trail`** — write/read a per-component changelog trail across versions; offline, scoped to a vault folder. - **`merge_vaults`** — safely merge two Obsidian vaults with conflict detection (sha256), `--dry-run` planning, and a Markdown audit log. - **`vault_repo_sync`** — sync a vault directory to a git remote (clone / pull / push) with auth guard rails. - **`variant_pack`** — generate a variant pack from a base vault asset (parametric mutations + manifest). - **`learn_from_my_corpus`** — mine the vault corpus to surface style/usage conventions and emit a structured learnings report. - **`create_shared_memory_bridge`** — wire a SharedMem In/Out bridge between TD processes (textures + CHOPs) for low-latency IPC. - **`build_sop_geometry`** — assemble a typed SOP geometry chain from a recipe of stages, with per-stage param validation (mirrors `build_chop_chain`). - **`sync_timecode`** — lock the show clock to external LTC / MTC / OSC / MIDI timecode and optionally drive the TD timeline. - **`manage_component_storage`** — structured read/write of COMP `storage` slots (get / set / delete / list) replacing raw exec. - **`enhance_build`** — apply targeted improvements to an existing built network and rescore via `score_build`, reporting before/after deltas. - **`create_growth_system`** *(Layer 1)* — build an organic growth/branching system (L-system flavour) with audio-modulated growth rate. - **`run_macro_script`** *(cli group)* — replay a recorded macro script of tool calls (closes the loop on Wave-4's `macro_recorder`). - **`tdmcp-agent log-tail`** — long-running, filterable tail of the bridge log stream with regex include/exclude. - **`tdmcp-agent record-fixtures`** — record live bridge HTTP traffic to a replayable msw fixture (adds `fetchImpl` plumbing on `buildToolContext`). - **`tdmcp-agent fanout`** — fan a single CLI invocation out to N remote tdmcp agents and aggregate results. - **`tdmcp-agent controller-bridge`** — bridge a MIDI/OSC control surface to CLI commands for hands-on driving. - **`tdmcp-agent voice`** / **`llm-voice`** — voice-driven copilot chat loop (push-to-talk → STT → tool dispatch). ### Changed (Wave 5) - `buildToolContext` accepts an optional `fetchImpl` override (forwarded to the TouchDesigner client) so the fixture-recorder CLI can wrap bridge calls. ### Changed (BEYOND Wave 1.5 deferred items) **Wave 1.5 — deferred items from v0.7.0**. Folds in the three follow-ups that were called out as deferred during the v0.7.0 integration pass: wiring the existing setlist tools onto the shared setlist schema, seeding the new Memory/ folder during `scaffold_vault`, and exposing the auto-tag heuristic on the save tools as an opt-in. ### Changed - `import_setlist` / `export_setlist_to_vault` now consume the shared `SetlistSchema` from `src/automation/setlistSchema.ts` (introduced in 0.7.0). Both still accept the legacy `tracks[]` shape; `import_setlist` additionally accepts the new `scenes[]` shape (`{id, title, cue, recipe, preset, steps, …}`), so a setlist authored for `setlist_runner` / `compose_cue_list` can be pre-staged with one tool call. `export_setlist_to_vault` now validates the frontmatter it writes against `SetlistSchema` before persisting, guaranteeing round-trip with `import_setlist`. - `scaffold_vault` now also seeds `Memory/README.md` and `Memory/style.md` (empty `StyleMemorySchema`) so the Memory layer added in 0.7.0 has a ready-to-merge home in fresh vaults. ### Added - `save_recipe_to_vault` and `save_component_to_vault` learn an opt-in `auto_tag?: boolean` (default `false`). When `true`, the deterministic `auto_tag_library_asset` heuristic runs against the captured network and the suggested tags are union-merged (dedup, case-insensitive) into the note's frontmatter alongside any caller-supplied `tags`. Default behaviour is unchanged. ### Added (BEYOND Wave 1 — live-show foundation + all P0) **Live-show foundation + all P0** — campaign `beyond_20260530` Wave 1. Ships the shared show-automation foundations (setlist/scene schema, memory-note schema, server-sampling-backed LLM fallback) and 13 P0 consumer features across artist controls, library/vault, and the CLI. Live-validated in TD 099. ### Added - **Show-automation foundations.** - **`src/automation/setlistSchema.ts`** — shared Zod setlist/scenes/steps schema with `parseSetlist` and normalizers, the single source of truth reused by `setlist_runner`, `create_scene_timeline`, and future vault setlist tools. - **`src/vault/memoryNote.ts`** — shared `MemoryNoteSchema` and `StyleMemorySchema` plus readers/writers/mergers consumed by `recall_similar_work`, `style_memory`, and `auto_tag_library_asset`. - **MCP-server-sampling LLM fallback** (`src/llm/samplingClient.ts` + `src/llm/resolve.ts`) — wired into `ctx.llm` so the local-copilot tier can ask the connected client to sample when no local model is configured. - **Six new artist Layer-2 tools.** - **`create_scheduler`** — Timer-CHOP-backed event scheduler primitive driving bar/beat/wall-clock callbacks. - **`create_auto_montage`** — beat/bar-synced media-bin sequencer with sequential / random / shuffle / weighted modes. - **`create_euclidean_sequencer`** — Bjorklund pattern generator driving step-callbacks for algorithmic rhythm. - **`create_preset_morph`** — multi-preset weighted parameter blend with a lookup table and Script-CHOP runner. - **`create_scene_timeline`** — scrubbable show-master timeline above `cue_sequencer` / `scheduler` for arranged sets. - **`create_glsl_material`** — `glslMAT` scaffolder with the F1/F2 preamble, `uTime`, `fragColor`, and a lint-warnings pass for common GLSL pitfalls. - **Four new library / vault tools.** - **`auto_tag_library_asset`** — auto-suggest tags for a vault asset by KB operator overlap (offline). - **`recall_similar_work`** — rank past memory notes by similarity to a new visual goal (Jaccard + tag + operator overlap, offline). - **`style_memory`** — show / read / update `Memory/style.md` (palettes / banned / favourites). - **`lint_recipe_library`** — Layer-3 tool plus a `scripts/lint-recipes.ts` runner for offline validation of the recipe library. - **Three new CLI verbs.** - **`tdmcp setlist run `** — headless setlist driver synced to a Beat CHOP. - **`tdmcp panic [on|off|toggle|freeze|unfreeze|clear|status]`** — one-word blackout / freeze with auto-detect of existing Blackout / Freeze nodes. - **`tdmcp dashboard`** — live TUI of performance, errors, and events (no new dependencies). ### Deferred (to Wave 1.5) - Migrating `importSetlist` / `exportSetlistToVault` to consume the new `src/automation/setlistSchema.ts` (still uses the legacy inline `tracks[]` schemas). - Extending `scaffold_vault` to seed the `Memory/` folder. - An opt-in `auto_tag?: boolean` on `save_recipe_to_vault` and `save_component_to_vault`. ### Security - **`rebuild_network` no longer `eval()`s the operator-type string.** The bridge script ran `eval(_type)` on a caller/LLM-controlled `nodes[].type`, an ungated arbitrary-Python path inside the TouchDesigner process reachable from an ordinary tool call. It now resolves the type by name off the `td` module (`getattr(td, _type)` guarded by `isidentifier()`), the same safe pattern `manage_checkpoint` already uses. Unknown types still fail-forward as warnings. - **TD bridge adds a loopback `Host`-header check.** `_check_host` complements the existing `Origin` guard to close a DNS-rebinding gap (the Web Server DAT binds all interfaces), mirroring the Node HTTP transport's `allowedHosts`. It is active only in the default token-less config; authenticated remote use via `TDMCP_BRIDGE_TOKEN` is unaffected, and a missing `Host` is allowed. - **Package downloads are pinned to GitHub and size-capped.** `downloadToFile` validates every hop (including redirects) against a GitHub host allowlist, requires HTTPS, and enforces a maximum response size — hardening against SSRF and oversized/runaway payloads. ### Added - **Five new library/packaging tools** (campaign Wave 4 — library surface), all live-validated in TD 099: diff_library_assets, import_recipe_from_url, export_palette_component, collect_project_assets, project_documentation_site. - **Four new AI/LLM features** (campaign Wave 6): caption_top, repair_network (tools; qa_unverified — offline unit-tested); teach_touchdesigner, design_brief (prompts; qa_pass). - **Nine new artist-control tools** (campaign Wave 3 — artist-controls surface of the discovery backlog). Eight were live-validated in TouchDesigner 099 (create → cook → zero post-cook errors); `create_blob_reactive` is built + unit-tested but still awaits a live-camera validation pass (noted on its entry below): - **`create_test_pattern`** — projector calibration source (grid / crosshair / color-bars / ramp / circle-grid) with a per-output number overlay; baked-GLSL, no probe risk. - **`create_text_crawl`** — multi-line crawl / ticker / typewriter text (vs single-string `create_kinetic_text`). - **`create_band_router`** — split audio into N EQ bands (`audiofilter` + `analyze rmspower`) and route each band level to its own target(s); output channels `band0…bandN`. - **`create_sidechain_pump`** — one-call "pump the whole rig on the kick": a Limit-CHOP-clamped ducking envelope bound to many targets with a single depth knob. - **`create_xy_pad`** — a draggable 2D XY gesture pad (Panel CHOP) driving target parameters by expression, with an optional Z slider. - **`create_time_echo`** — per-pixel time effect on a source TOP: echo trails (feedback + Level-TOP decay), slit-scan and time-displace (`timeMachineTOP`). - **`create_capture_loop`** — bidirectional Spout/Syphon/NDI bridge (receive + publish in one container), anti-feedback by design. - **`create_vector_lines`** — image/video → pulse-captured Trace-SOP vector geometry composited back over the source. - **`create_blob_reactive`** — camera/TOP blob-position tracking (`blobtrackTOP`) bound to parameters (blob-channel layout pending a live-camera validation pass). - **`.safeskillignore`** so the SafeSkill scanner skips generated knowledge-base data, build output and binary media (the source of the substring false positives) and focuses on the actual server code. ## [0.6.1] - 2026-05-30 Release-hygiene and documentation patch that makes 0.6.x consistent across npm, the GitHub Release and the tag. **0.6.0 shipped to GitHub only** (the `.mcpb` asset) and never reached npm, because the release workflow skips `npm publish` when `NPM_TOKEN` is unset; 0.6.1 is the npm catch-up and folds in the fixes and docs that landed on `main` after the 0.6.0 tag was cut. No tool API changes. ### Fixed - **`set_parameter_expression` exec-fallback no longer drops the mode flip.** The endpoint path already flipped `par.mode` via `type(par.mode)`, but the legacy whole-batch exec fallback (used only against a pre-0.6.0 bridge) still assigned the bare `ParMode.EXPRESSION` / `.BIND` / `.CONSTANT`, which `NameError`'d and silently left the parameter in Constant mode. The fallback now resolves the enum the same way (`type(_par.mode).EXPRESSION`), so expression/bind/constant flips also land on older bridges. ### Added - **Controller-level regression test for the structured REST routes.** A new `StructuredEndpointTests` proves `POST /api/connect`, `POST /api/disconnect`, `GET /api/logs`, `GET …/params?modes=true`, `PATCH …/params/

/mode` and `GET` / `PUT …/text` dispatch to their services **and survive `TDMCP_BRIDGE_ALLOW_EXEC=0`** — previously asserted only by code inspection. ### Changed - **`docs/reference/bridge-api.md`** now lists the seven structured endpoints added in 0.6.0 and documents that they are not behind the exec gate. - **Advertised tool count corrected to 179** in the README and docs home page (0.6.0 added four tools; the hand-written copy still said 175 — the generated tools reference was already correct). - **PT prompt cookbook** gains the "Componentes reutilizáveis & documentação" section that previously existed only in the English guide. - **Release workflow** writes a prominent job-summary banner when `npm publish` is skipped (missing `NPM_TOKEN`) or succeeds, so a GitHub-only release can't pass unnoticed again. ## [0.6.0] - 2026-05-29 TouchDesigner-depth and library wave. Seven P0 features sharpen the bridge's read/write fidelity and add two performance instruments plus a library contact-sheet. The bridge gains **structured REST endpoints** for the operations that previously rode the raw-Python escape hatch — connect/disconnect, parameter modes + expression/bind, DAT text, and a logs feed backed by an in-bridge Error DAT — and the affected tools were rewired **endpoint-first with an exec-fallback**, so they keep working against an older bridge while routing through the fast, exec-gate-free path on a current one. This also fixes a silent parameter-mode bug that left `set_parameter_expression` writing the expression text without ever flipping the parameter into Expression/Bind mode. ### Added - **`get_td_node_flags`** (CLI `nodes flags`) — read an operator's flags (bypass / render / display / lock / allowCooking / clone), index-aware input wiring (`wires_in`), and position / comment / color in one call. Supports recursive sweeps with `max_nodes`, an `only_problems` filter, and a per-node `suspect_reason` (e.g. "bypass on"). `node_detail` / `NodeDetailSchema` / `serialize_network` were extended with the same flags / wiring / comment / color fields (back-compatibly). - **`create_modulators`** (CLI `modulators`) — a BPM-synced multi-LFO bank: tempo-locked sine / saw / noise modulators on one Null with named output channels, a master Rate/Depth, and a paused-timeline warning. Bind `mod_out` to any parameter to make a network breathe in time with the music. - **`create_look_bank`** (CLI `look-bank`) — a snapshot + A↔B-morph instrument: capture the current look (morph-safe — pulse and string parameters are skipped), store named looks, and recall them with an instant snap or a quantized, timed morph, plus a live A↔B blend knob. - **`generate_library_index`** (CLI `library-index`) — render a Markdown contact-sheet of a vault's saved recipes and components, embedding each asset's preview thumbnail (`![[stem.png]]`, or _(no preview)_ when none was captured). - **Recipe / component preview thumbnails** — `save_recipe_to_vault` and `save_component_to_vault` accept `preview_top` / `thumbnail` and capture a sibling `.png` next to the saved note, embedding it after the frontmatter. Thumbnail capture **never throws**: a capture failure leaves the note intact and unembedded. - **New bridge REST endpoints** (no exec gate — they survive `TDMCP_BRIDGE_ALLOW_EXEC=0`): `POST /api/connect` + `POST /api/disconnect` (index-aware multi-input packing and disconnect-by-source); `GET …/params?modes=true`, `PATCH …/params/

/mode` and `GET`/`PUT …/text` (parameter modes, expression/bind, and DAT text); and `GET /api/logs` backed by a new in-bridge **Error DAT** (scoped to the artist's `/project1` network, header-name column mapping) with edge-triggered `cook.error` / `error.cleared` events. ### Changed - **`connect_nodes`**, **`disconnect_nodes`**, **`read_parameter_modes`**, **`set_parameter_expression`**, **`edit_dat_content`**, **`set_dat_content`** and **`get_bridge_logs`** now call their dedicated REST endpoint first and **fall back to the raw-Python path only when that endpoint is missing on an older bridge** — a current bridge's validation errors surface instead of silently retrying via exec, and connection/timeout errors still propagate — so they work against both current and older bridges. `connect_nodes` now reports the actual packed input slot; `edit_dat_content` refuses to write when the replacement target matches zero or more than one location. ### Fixed - **Silent parameter-mode bug in `set_parameter_expression`** — setting an expression or bind previously wrote the expression text but never switched the parameter out of Constant mode (a latent `ParMode` `NameError` meant the mode change was silently dropped). The new `PATCH …/params/

/mode` endpoint resolves the enum via `type(par.mode)` and the parameter now actually flips to Expression / Bind (verified live). ### Live validation All seven features passed QA: the four PR gates were green (1614 tests, 15/15 recipes, 86 bridge tests) and each feature's bridge logic was validated live in TouchDesigner (connect/disconnect packing, the parameter-mode flip, the Error DAT scope + header mapping, the modulator and look-bank networks cooking with zero errors). The following were validated by static check + live-mechanism only and are **pending an end-to-end re-check after the owner reinstalls the bridge and restarts the server** (acceptable per release policy): - MCP tool calls for all seven features routed through the **new HTTP dispatcher** (the relocated bridge logic itself was validated live; the live routing through the controller was not). - `TDMCP_BRIDGE_ALLOW_EXEC=0` survival of the five new structured routes (static-passed: no exec gate on any of them). - Edge-triggered `cook.error` / `error.cleared` events from the bridge's frame hook. - The save-tool thumbnail end-to-end (sibling PNG written + embedded) against a live vault, and `generate_library_index` rendering the contact-sheet from real assets. - The live client→bridge round-trip shape for the seven rewired tools (the Zod schemas were diffed statically against the bridge dicts produced live; the live HTTP round-trip is pending). ## [0.5.0] - 2026-05-29 Phase 13 plus the dotsimulate LOPs integration. The focus shifts from *generating* visuals to **packaging, documenting and cheaply operating** them: reusable components (build → parameterize → script → package), project intelligence, token-cheap agent-DX primitives, and external-clock locking. It also adds a way to drive tdmcp from *inside* TouchDesigner via dotsimulate's LOPs "MCP Client" plus an optional curated tool profile for autonomous in-TD agents — additive and backward-compatible (the default profile is `full`). Every new tool was built → integrated → validated with automated coverage; live TD validation is called out where hardware or an open TD session is still required. ### Added - **`add_custom_parameters`** (CLI `add-params`) — append a custom-parameter page (Float/Int sliders, Toggle, Menu, Str, Pulse, RGB, XYZ) to any COMP so a generated network becomes a tunable, reusable component. Sets defaults, slider ranges (`normMin`/`normMax`) and optional hard clamps; a parameter that already exists is **skipped with a warning**, never overwritten, so re-running to add one more knob is safe. - **`scaffold_extension`** (CLI `scaffold-ext`) — give a COMP a Python **extension class**: a Text DAT holding the class (with optional method stubs), wired into an extension slot, optionally **promoted** (members callable directly on the COMP), and reinitialized. The extension parameter names vary by TouchDesigner build, so the tool **probes** for them (noting any difference as a warning) instead of hardcoding. With `add_custom_parameters` (knobs) and `manage_component` (save as `.tox`), this completes the build → parameterize → script → package story — see the new [Reusable components](https://pantani.github.io/tdmcp/guide/components) guide. - **`analyze_project`** (CLI `analyze`) — find likely-dead operators, broken external-file dependencies, and orphan COMPs, plus a dependency map (op()/Select refs + CHOP exports). Conservative, with a reason per flag. Complements `describe_project`. - **`generate_readme`** (CLI `readme`) — a Markdown project document: family/type counts, a custom-parameter table, inputs/outputs, child inventory, external-file deps, and an optional preview thumbnail. - **`edit_dat_content`** (CLI `dat-edit`) — surgical old/new string replace in a Text/Table DAT, requiring a unique match unless `replace_all` is set. - **`set_dat_content`** (CLI `dat-set`) — overwrite a DAT's whole text, with a `confirm_wipe` anti-wipe guard that refuses silent clears. - **`batch_operations`** (CLI `batch`) — run many create/connect/setParam ops in one fail-forward call (per-item warnings; not transactional), reusing the Layer-1 network builder. Distinct from `set_parameters_batch` (params only). - **`manage_annotation`** (CLI `annotate`) — create titled Annotate-COMP boxes, set per-op comments, list a network's annotations, and list the ops a box geometrically encloses — self-documenting networks. - **`write_agent_guide`** (CLI `agent-guide`) — emit a project-local `CLAUDE.md`/`AGENTS.md` seeded with tdmcp operator conventions + TD render-coordinate rules. - **`set_perform_mode`** (CLI `perform-mode`) — toggle a perform-mode flag (stored on the TD root + `ui.performMode`) so tools can skip nonessential compute during a live show. The built-in guard currently suppresses preview captures; other tools can opt in by reading `tdmcp_perform_mode`. - **TD-depth foundation:** `read_parameter_modes` (CLI `nodes modes`) reads constant / expression / bind / export state for a node's parameters, and `set_parameter_expression` (CLI `nodes expr`) switches a single parameter into expression mode with rollback on failure. `snapshot_td_graph compact` now preserves reactive parameter state when possible. - **Live controls / VJ tools:** `bind_audio_reactive` (CLI `bind-audio`), `create_transition` (`transition`), `create_live_source` (`live-source`), `create_layer_stack` (`layer-stack`), `create_media_bin` (`media-bin`), `create_keyer` (`keyer`), `create_datamosh` (`datamosh`), and `create_displacement_warp` (`displace-warp`). - **CLI/DX:** JSON config files and named profiles (`TDMCP_CONFIG_FILE`, `TDMCP_PROFILE`), `tdmcp install-client`, `tdmcp-agent run `, `--params-file`, `--params -`, `--td-host`, `--td-port`, `--timeout`, shell completion, `--version`, `--quiet`, `--no-color`, and advisory `doctor --fix`. - **AI prompt/copilot surface:** new prompts for `fix_reactivity`, `recover_show`, `auto_vj_director`, `color_story`, `lyric_show`, `setlist_planner`, `visual_ab_compare`, `motion_critique`, and `explain_param`; a prompt catalog resource at `tdmcp://prompts`; and a `creative` copilot tier. - **Library / packaging tools:** `browse_library`, `inspect_component_manifest`, `make_portable_tox`, `export_recipe_bundle`, `import_recipe_bundle`, `validate_library_asset`, `scaffold_recipe_template`, `attach_docs_as_assets`, `local_marketplace_index`, `component_link_health`, `refresh_asset_previews`, and `install_library_package`. - **Body-tracking CLI + recipe:** 1:1 CLI commands for the MediaPipe body-tracking tools that shipped in 0.4.0 (`body-tracking`, `pose-track`, `skeleton`, `body-reactive`), plus a new recipe **`body_tracking_reactive`** — 33 MediaPipe landmark dots with a feedback motion trail. Re-validated live against the engine. - **`analyze_screenshot`** prompt — captures a node's preview + topology + node errors and diagnoses what it shows or why it looks wrong ("why is it black?"). - **Feature-build harness** (`.claude/`): a `tdmcp-tool-builder` skill + `tdmcp-feature-lead` / `tdmcp-tool-builder` agents that build tool batches as parallel one-tool-per-agent waves with a single-writer integrator. - **`scripts/tdmcp-lops.mjs`** — a dependency-free launcher for dotsimulate's LOPs MCP Client. Point the LOPs `command` at it; it injects the hardened env (`TDMCP_RAW_PYTHON=off`, `TDMCP_TOOL_PROFILE=safe`) then execs `dist/index.js`, since LOPs' `servers_config.json` has no documented `env` field. - **LOPs integration guide** (EN + PT) — setup, the hardened `servers_config.json` snippet, the TD → tdmcp → bridge → TD architecture, and an explicit callout that this does **not** replace the local `tdmcp chat` copilot. Plus reference docs for the new env var and the in-TD topology. #### Phases 14–15 — live mixing, parameter fidelity, network round-trip & creative direction The post-discovery feature wave: built as parallel one-tool-per-agent waves with a single-writer integrator, all offline-gated (typecheck + build + Biome + vitest + recipes + bridge tests). **TouchDesigner was offline during the build, so every new tool/prompt is shipped with offline unit coverage and its live create→cook→preview validation marked UNVERIFIED-pending** — each TD-touching tool carries a `probe` block (and `extra.unverified`) that surfaces the real TD API on its first live run, and is fail-forward (per-item warnings, never throws). - **Live mixing & external content** — `create_transition` (CLI `transition`): A→B transitions over a 0–1 Progress knob (dissolve / luma_wipe / slide / zoom / glitch_cut; folds in the planned `transition_designer` prompt). `create_live_source` (`live-source`): an input layer (screen-grab / NDI / Syphon-Spout / camera / video stream) → a previewed Null — default screen-grab is zero-permission (camera is opt-in; can hang TD on a macOS modal). `create_layer_stack` (`layer-stack`): an N-layer compositor with per-layer blend + opacity + mute/solo and a generated control strip. `create_media_bin` (`media-bin`): a folder-fed clip bin (Movie File In + Switch) with Index/Next/Prev + crossfade-on-switch. `create_keyer` (`keyer`): chroma/luma/rgb key + matte composite over a background. - **One-shot reactivity** — `bind_audio_reactive` (`react-audio`): auto-maps a COMP's numeric knobs to audio bands (brightness↔level, scale↔bass, hue↔treble) and wires them in one call, with a master Reactivity knob. `create_data_reactive` (`react-data`): the data counterpart, mapping live `create_data_source` channels onto params with per-mapping range remap. `create_envelope_follower` (`envelope`, **experimental**): attack/release + gate/duck (sidechain a layer to the kick), beyond `bind_to_channel`'s plain Lag. - **Signature effects** — `create_datamosh` (`datamosh`), `create_displacement_warp` (`warp`), `create_halftone` (`halftone`), `create_feedback_tunnel` (`feedback-tunnel`), and `create_text_3d` (`text-3d`, extruded 3D type). Plus **`apply_post_processing` gains five chainable GLSL effects**: `halftone`, `dither`, `crt`, `mirror`, `vhs`. - **Sequencing & set navigation** — `create_set_navigator` (`set-nav`): a QLab-style cue-list navigator (Index/Next/Prev/Go, GO-on-beat). `create_beat_grid_sequencer` (`beat-grid`): a bar/beat step grid firing a param or cue per active step (the deterministic counterpart to `create_autopilot`'s drift and `create_cue_sequencer`'s linear list). - **Parameter fidelity & wiring** — `read_parameter_modes` (`params-modes`): reports each parameter's mode (constant/expression/export/bind) + raw expr/bind/export, not just the value — the precondition for any faithful serialize/diff. `set_parameter_expression` (`set-expr`): set a parameter to an expression/bind/constant without the raw-Python escape hatch. `disconnect_nodes` (`disconnect`): remove input wire(s) — the inverse of `connect_nodes`. - **Network round-trip & introspection** — `serialize_network` (`serialize`) + `rebuild_network` (`rebuild`): a COMP subtree ↔ a diffable JSON spec (params with modes/exprs + wires), reconstructed via the batch builder. `inspect_op_extensions_storage` (`inspect-comp`): read back a COMP's storage, promoted extension members, and custom-parameter definitions (the read side of the reusable-component loop). `get_node_state_runtime` (`node-state`): per-operator runtime telemetry (cook time/count, resolution, channels, GPU memory). `get_bridge_logs` (`logs`): recent cook errors/warnings (+ best-effort textport) for less-blind debugging. - **Data-driven & dimensional** — `create_replicator` (`replicator`): clone a template COMP per Table-DAT row. `multipass_3d_depth` (`multipass-3d`): a 3D scene with a Render + SSAO pass and a synthetic Depth output that feeds `create_depth_displacement`/`create_depth_silhouette` without a depth camera. `create_pop_field` (`pop-field`, **experimental — POPs are experimental in this build**): a first Layer-1 generator for TD's GPU POP family; held for live render-path validation. - **MIDI (hardware-gated)** — `create_midi_note_reactive` (`midi-notes`): MIDI notes → per-note reactive channels, with a **synthetic source** that previews without gear (the device path is held pending hardware). `create_midi_map` (`midi-map`): one-call controller presets (APC Mini / Launchpad / MIDI Mix / nanoKONTROL) — CC/note maps are best-effort and held pending hardware. - **Vault library** — `save_component_to_vault` (save a built COMP as a `.tox` + a referencing note), `browse_vault_library` (list recipes/shaders/presets/components/setlists), `capture_to_vault` (still captures into a dated gallery look-book note), and `export_setlist_to_vault` (serialize live cues/tempo back to an `import_setlist`-compatible note — closing the round-trip). MCP-only (no CLI), gated on `TDMCP_VAULT_PATH`. - **AI prompts (11 new)** — live operation: `fix_reactivity` (diagnose a wired-but-dead signal), `recover_show` (fast mid-show panic recovery), `auto_vj_director` (hands-free AI VJ over the event stream). Creative direction: `color_story`, `setlist_planner`, `lyric_show`, `genre_visual_language`. Critique & matching: `visual_ab_compare`, `motion_critique`, `match_reference_loop`. Education: `explain_param` (grounded in the 629-operator KB). - **`tdmcp://prompts` resource** — a catalog of every MCP prompt (name + one-line purpose) so a model — including the local copilot, which can't see MCP prompts — can discover the creative recipes available. #### CLI, config & copilot DX (post-discovery follow-on) - **Config files + named profiles** — `loadConfig` optionally reads a `tdmcp.json` / `.tdmcprc` / `~/.config/tdmcp/config.json` with named `profiles`, so an artist can save per-venue setups and switch with `--profile club` instead of editing their shell rc. Precedence: defaults < file base < file profile < env < CLI flags. The stdio server honors it too (`TDMCP_PROFILE`); env still wins, so existing setups are unchanged, and a malformed file warns rather than crashing. - **Per-call CLI overrides** — global `--profile` / `--config` / `--td-host` / `--td-port` / `--timeout` on any `tdmcp-agent` command, plus a `config` command that prints the effective resolved config (secrets redacted) or, with `--write-env`, a paste-ready export block. - **`doctor` upgrades** — a new **Tools** check (surfaces `TDMCP_RAW_PYTHON` / `TDMCP_TOOL_PROFILE` lockouts so a missing tool has a named cause); `--fix` appends a "Suggested fixes" section (a remediation command per non-passing check); `--output json` + `-q/--quiet` make it scriptable/CI-friendly; honors the global config flags. - **CLI ergonomics** — `-V/--version`; a "did you mean" suggestion on an unknown command; `--params -` (stdin) and `--params-file ` to complete the Unix-filter story; `-q/--quiet` to silence the stderr summary; and `watch --filter`/`--exclude ` to select event types. - **Local copilot tier** — `search_operators` + `list_recipes` added to every tier (read-only KB browse), and a new **opt-in `creative` tier** (a `creative` checkbox) that adds a curated set of safe Layer-1 generators (`create_generative_art` / `create_feedback_network` / `create_audio_reactive`) so the local model can build a whole look offline. Off by default — small-model generator-call accuracy is unbenchmarked. ### Changed - **`apply_post_processing`** gains five chainable inline-GLSL effects: `halftone`, `dither`, `crt`, `mirror`, `vhs`. - **`create_external_io`** gains a `video_device_out` kind (SDI / capture-card via a Video Device Out TOP; device par probed defensively) — hardware-gated, build-only verification. - **`get_td_info`** now warns when the **running** Python bridge is older than this build (comparing to the shipped bridge version), pointing at `reload_bridge` — catching the recurring "edited td/ but it didn't take effect" gotcha. - **`sync_external_clock`** gains a `mode` (`tap` | `ableton_link` | `midi_clock`): Ableton Link locks to a Link session via an Ableton Link CHOP; MIDI clock derives BPM from 24-PPQN timing. `tap` stays the default. Link/MIDI are hardware-gated (manual Bpm fallback when no source is present). - **`snapshot_td_graph`** gains a `compact` mode — hoists per-type default parameters and delta-encodes each node for token-cheap whole-COMP reads. - **`TDMCP_TOOL_PROFILE`** (`full` | `safe`, default `full`) — `safe` additionally hides the destructive / raw-code tools, including DAT overwrite/edit, component/package writes and preview-asset writes, as a strict superset of `TDMCP_RAW_PYTHON=off`. Use it to hand an autonomous in-TD agent a curated, non-destructive toolset. [0.8.3]: https://github.com/Pantani/tdmcp/compare/v0.8.2...v0.8.3 [0.8.2]: https://github.com/Pantani/tdmcp/compare/v0.8.1...v0.8.2 [0.8.1]: https://github.com/Pantani/tdmcp/compare/fa7d33c2a8093d85cbad6226f62f28714a0af8fb...v0.8.1 [0.8.0]: https://github.com/Pantani/tdmcp/compare/v0.7.1...fa7d33c2a8093d85cbad6226f62f28714a0af8fb [0.7.1]: https://github.com/Pantani/tdmcp/compare/v0.7.0...v0.7.1 [0.7.0]: https://github.com/Pantani/tdmcp/compare/v0.6.1...v0.7.0 [Unreleased]: https://github.com/Pantani/tdmcp/compare/v0.13.2...HEAD [0.13.2]: https://github.com/Pantani/tdmcp/compare/v0.13.1...v0.13.2 [0.13.1]: https://github.com/Pantani/tdmcp/compare/v0.13.0...v0.13.1 [0.13.0]: https://github.com/Pantani/tdmcp/compare/v0.12.0...v0.13.0 [0.12.0]: https://github.com/Pantani/tdmcp/compare/v0.11.0...v0.12.0 [0.11.0]: https://github.com/Pantani/tdmcp/compare/v0.10.0...v0.11.0 [0.10.0]: https://github.com/Pantani/tdmcp/compare/v0.9.0...v0.10.0 [0.9.0]: https://github.com/Pantani/tdmcp/compare/v0.8.3...v0.9.0 [0.6.1]: https://github.com/Pantani/tdmcp/compare/v0.6.0...v0.6.1 [0.6.0]: https://github.com/Pantani/tdmcp/compare/v0.5.0...v0.6.0 [0.5.0]: https://github.com/Pantani/tdmcp/compare/v0.4.0...v0.5.0 ## [0.4.0] - 2026-05-27 Fifteen new tools and prompts, built as a coordinated parallel pipeline (design → develop → QA → deploy) and live-validated against TouchDesigner 2025.32820: live-performance control, signature 3D/GPU visuals, more creation primitives, spatial output, data + audio I/O, and AI authoring prompts. ### Added - **`create_cue_sequencer`** (CLI `cue-sequencer`) — a bar-quantized cue timeline: a Beat CHOP + CHOP Execute DAT advances through an ordered list of steps, recalling/morphing each step's cue on the beat. The deterministic, musically-timed counterpart to `create_autopilot`. - **`create_stage_dashboard`** (CLI `dashboard`) — one unified web performance surface from a Web Server DAT: cue-launch buttons + master faders + a panic blackout + a live beat/VU readout. Trusted networks only (accepts writes without auth, like the bridge). - **`create_raymarch_scene`** (CLI `raymarch`) — a self-contained GLSL TOP raymarcher: SDF scenes (sphere-field / menger fractal / tunnel) with camera, step-count and color controls — the volumetric complement to `create_shader_lib`. - **`detect_tempo`** (CLI `detect-tempo`) — auto-BPM from audio onsets (no tapping): inter-onset intervals → median → BPM on a Null CHOP, optionally driving the global tempo. Complements `sync_external_clock`. Experimental — BPM lock needs live tuning. - **`create_palette`** (CLI `palette`) — a color palette / gradient generator: harmony rules (complementary/triad/analogous/tetrad/monochrome) or sampled from a source TOP → a Ramp TOP + a swatch CHOP, ready for `create_color_grade` / `generate_from_moodboard` / `bind_to_channel`. - **`create_pbr_scene`** (CLI `pbr-scene`) — a 3D scene with a PBR material (metallic/roughness/base color) + an environment light rig for image-based lighting, beyond `create_3d_scene`'s basic light. - **`create_particle_flock`** (CLI `flock`) — boids-style GPU particle flocking (separation/alignment/cohesion in a feedback-TOP velocity loop) feeding TOP-instancing — a behavioral complement to `create_gpu_particle_field`. - **`create_point_cloud`** (CLI `point-cloud`) — render a point cloud from a depth/luminance map or a synthetic source via texture-packed TOP-instancing, with depth-scale / point-size / spin. - **`create_data_source`** (CLI `data-source`) — ingest live external data (JSON/CSV over a Web Client DAT, OSC In, or Serial) onto a binding-ready Null CHOP, the input that feeds `create_data_visualization` / `bind_to_channel`. - **`create_generative_audio`** (CLI `gen-audio`) — synthesize audio (oscillator / FM / noise) onto a Null CHOP, with optional opt-in audio-device output — generate sound, not just react. - **`create_cubemap_dome`** (CLI `cubemap-dome`) — a true cube-map render (Render TOP in cube-map mode → GLSL fisheye/equirectangular remap) for planetarium domes / 360, the higher-fidelity follow-up to `create_dome_output`. - **`create_led_mapper`** (CLI `led-mapper`) — pixel-map regions of a source TOP to an LED fixture layout (strip/grid; horizontal/vertical/serpentine) → per-pixel colors out as DMX/Art-Net, building on `create_external_io`'s `artnet_out`. - **`scaffold_genre`** (CLI `genre`) — genre show scaffolds (techno / ambient / installation): a styled starting network with a genre-appropriate tempo, look and palette, beyond `scaffold_show`'s generic skeleton. - **`text_to_recipe`** prompt — author a schema-valid recipe JSON (matching `RecipeSchema`) from a plain-language description, ready to save under `recipes/` and instantiate with `apply_recipe`. - **`style_reference`** prompt — recreate a reference look (image or text description) by mapping it onto an ordered plan of concrete tdmcp tool calls + parameters. [0.4.0]: https://github.com/Pantani/tdmcp/releases/tag/v0.4.0 ## [0.3.1] - 2026-05-27 Packaging and docs for the Anthropic Connectors Directory submission (Desktop Extension path). No runtime/tool behaviour changes. ### Changed - The one-click Claude Desktop bundle is now built as **`.mcpb`** (MCP Bundle), the current Anthropic format — the build script already preferred the `@anthropic-ai/mcpb` packer, so this renames the output and the `build:dxt` → `build:mcpb` script. Legacy `.dxt` files still install in Claude Desktop. ### Added - **Privacy policy** page (EN + PT) at `/privacy`, documenting that tdmcp runs entirely locally, collects no data, and has no telemetry — required for the Connectors Directory submission. ## [0.3.0] - 2026-05-27 Everything built on top of 0.2.0, in one release: a scriptable CLI and developer-experience tooling, musical and beat reactivity, live-performance instruments (cues, macros, control surfaces, phone remote), advanced creation (video, 3D, mixing, projection mapping, keyframes, simulations, dimensional 3D / depth & spatial mapping), assistant intelligence (operator search, documentation, AI prompts), and robustness & export (render to disk, performance hunting, snapshots, recipes). ### Added - **Phase 12 — Dimensional (3D, depth & spatial mapping):** five Layer-1 generators that take visuals off the flat plane, each built → verified → previewed live in TouchDesigner. - **`create_3d_audio_reactive`** — a 3D scene that reacts to sound (CLI `audio3d`). `instanced_bars` renders a row of boxes/spheres whose **per-bar height** tracks the FFT spectrum (one CHOP sample per bar drives `instancesy` through a CHOP instance source) — a 3D spectrum bar-graph; `bass_pulse` swells a single primitive with RMS energy. The 3D counterpart to `create_audio_reactive`. - **`create_dome_output`** — GLSL-remap a source TOP to **fisheye** or **equirectangular** for planetarium domes / 360 projection (CLI `dome`), the curved single-output complement to `create_multi_output`'s flat tiling. - **`create_mesh_warp`** — map a source onto a **curved surface** via a deformable textured grid: a Point-SOP Z deform (bulge / wave / cylinder) of a `gridSOP` textured through a Constant MAT, beyond the flat corner-pin — for domes, columns, sculptures. Output ready for `setup_output` (CLI `mesh-warp`). - **`create_depth_displacement`** — push a plane into real 3D relief by a **depth / luminance map** (camera / movie / synthetic) through a GLSL MAT vertex stage — true 2.5D geometry, with an Execute-DAT keep-alive for still sources (CLI `depth-displace`). Distinct from `create_depth_silhouette` (a flat mask). - **`create_gpu_particle_field`** — a high-count **GPU particle field** (side², up to 512²≈262k): position/velocity **feedback-TOP** loops (curl-noise / gravity) feed **TOP-instancing**, flowing as curl-noise streams well beyond the CPU `create_particle_system` (CLI `gpu-particles`). Optional reactivity energises the field live — `audio` from mic/line RMS, `motion` from camera frame-difference energy — both bound to the velocity shader's `uReact` uniform. - **Local LLM copilot (`tdmcp chat`, alias `tdmcp llm-run`)** — a browser chat UI driven by a local LLM (Ollama by default; any OpenAI-compatible endpoint via `TDMCP_LLM_BASE_URL`) for **simple tasks**, wired to the same bridge. Given a curated, **safe** tool subset (Layer-3 inspect/CRUD + a few Layer-2; no Layer-1 system generators, no raw Python), with token streaming, cancel, a **read-only** tier, live model/endpoint switching, a one-click model **pull**, an **Escalate** handoff that copies a paste-ready prompt for Claude/Codex (same bridge, no state to move), and persistent history. **Auto-starts Ollama** when the local daemon isn't running (detached, left running so quitting the chat never takes the model offline); opt out with `--no-ollama`. Default model **`qwen2.5:3b`** — benchmarked 100% tool-calling on the simple-task workload, faster and lighter than 7B/14B (sub-3B is flaky; `llama3.1:8b` weaker at tool use). - **`record_movie`** — record a TOP to a movie file (.mov/.mp4) via a Movie File Out TOP, with start/stop and an optional `seconds` auto-stop for capturing a fixed-length loop; stop also removes the recorder node it added so nothing lingers (CLI `movie`). Complements render_output — use render_output per frame for individual numbered stills. - **`scaffold_show`** — create a starting skeleton for a live show (a master output Null + a tempo beat clock) so a set has a frame to build into (CLI `init`). - **CLI `repl`** — an interactive mode that runs commands line-by-line (quotes preserved for JSON `--params`). - **`create_motion_reactive`** — a camera/video analysis chain that exposes ready-to-bind reactive channels (overall brightness + frame-to-frame motion energy) on a Null CHOP, with a Sensitivity knob (CLI `motion-reactive`). The camera counterpart to extract_audio_features: bind a parameter to `op('…/motion_reactive/features')['motion']` and it reacts to movement. Source can be the live camera, a movie file, a synthetic pattern (for testing without a camera), or an existing TOP. A small Execute DAT keeps the analysis cooking so the signals stay live before anything is bound. (Optical flow is unsupported on macOS, so flow direction isn't exposed.) First of the Phase 7 "stage I/O & sensor reactivity" tools. - **`create_text_overlay`** — composite styled text (font size, hex color, h/v alignment) over a visual through a Text TOP + Composite TOP, or on its own transparent background, output as a Null (CLI `text`). For lyrics, titles, song names or credits — distinct from the vault's `bind_vault_text` (a data-sync of a Text DAT); this is a finished visual layer. - **`create_autopilot`** — a beat-driven auto-VJ: a Beat CHOP + CHOP Execute DAT that, every N beats, either randomizes a target COMP's numeric controls (a hands-free drift set by Amount) or cycles through its stored cues, so a set keeps evolving on its own (CLI `autopilot`). Live Active / Beats / Amount knobs pause or retune it on stage. Reuses the tempo clock, randomize_controls and manage_cue mechanisms (validated live: controls drift each beat, Active pauses). - **`create_multi_output`** — fan a master TOP across N projectors/displays: each output is a cropped horizontal or vertical slice resized to full projector resolution and ended on a Null, ready for setup_output; with `as_windows`, each tile also gets a borderless Window COMP offset across the desktop onto its own display (CLI `multi-output`). An `overlap` adds **edge-blending** — tiles widen into their neighbours and a GLSL feather fades the shared seams so physically- overlapping projectors blend smoothly. The multi-projector counterpart to setup_output's single window (validated live: a ramp split into seamless halves, and the feather fading interior seams to transparent while leaving the canvas edges full). - **`sync_external_clock`** — lock the project tempo to a live source so beat-synced visuals follow the music: a Bpm knob writes the global tempo (`op('/').time.tempo`) and a Tap pulse beat-matches by ear (averaging taps into a BPM), driving every Beat CHOP downstream — `create_tempo_sync` and `create_autopilot` follow (CLI `clock-sync`). Validated live: the knob drives the global tempo (128→174) and taps are recorded. (Dedicated MIDI-clock / Ableton-Link sync is a planned follow-up.) - **Signature VJ effects** — `create_strobe` (beat-syncable strobe/flash, square LFO → brightness; CLI `strobe`), `create_kaleidoscope` (N-fold radial mirror via a GLSL polar-fold; CLI `kaleidoscope`), `create_glitch` (RGB-shift + noise displacement, non-device default source; CLI `glitch`), `create_kinetic_text` (animated / beat-flashed lyric typography; CLI `kinetictext`). - **Deeper musical reactivity** — `create_spectrum` (N-band FFT via an Audio Spectrum CHOP → a per-band Null for binding; CLI `spectrum`), `detect_onsets` (kick/snare/hat transient detection built from primitives — band RMS → moving baseline → threshold — with an optional `onset` WebSocket event; CLI `onsets`), `create_waveform` (time-domain oscilloscope; CLI `waveform`). The frequency / transient / time-domain complements to `extract_audio_features`. - **Creation** — `create_color_grade` (lift/gamma/gain + saturation/hue + optional LUT; CLI `colorgrade`), `import_model` (3D model file → Geo/Camera/Light/Render, primitive fallback; CLI `model`), `create_shader_lib` (curated GLSL pack: tunnel/raymarch/fractal/metaballs/plasma; CLI `shaderlib`), `create_video_synth` (analog-synth lissajous/interference/scanline patterns; CLI `videosynth`), `create_depth_silhouette` (silhouette / body mask from a depth or video source, device-free default; CLI `silhouette`). - **Live-performance ergonomics** — `create_panic` (instant Blackout + Freeze safety control; CLI `panic`), `create_clip_launcher` (Ableton-style grid of cue-trigger buttons, reusing manage_cue's recall/morph engine; CLI `launcher`). - **AI prompts** — `text_to_shader` (author + validate a GLSL TOP from a description), `audio_to_show` (plan a full reactive set from a track), `auto_fix` (a detect → diagnose → fix → re-check repair loop). - **CLI `doctor`** — a one-shot environment diagnostic (TD bridge, local LLM copilot, vault, config) with a plain-language pass/warn/fail report; the exit code reflects critical checks only. - **Oscilloscope waveform + flash-to-transparent text** — `create_waveform` now renders a real scope LINE (CHOP-to-SOP → Geometry → orthographic Render TOP) instead of a brightness strip; `create_kinetic_text`'s flash modulates ALPHA so the text vanishes between flashes (over a background) instead of going black. - **`create_external_io` output kinds** — `rtmp_out` (stream a TOP over RTMP via a Video Stream Out TOP — NVIDIA/Windows) and `artnet_out` (send a CHOP out as Art-Net/sACN via a DMX Out CHOP, for LED pixel-mapping & stage fixtures). - **`bind_to_channel` smoothing** — optional `attack`/`release` (or `smooth`) seconds insert a Lag CHOP between the channel and the parameter, so reactivity follows a clean envelope instead of flickering on the raw signal. - **`manage_cue` beat-quantized recall** — an optional `quantize` ("off"/"beat"/"bar") defers a recall/morph to the next musical boundary so scene changes snap to the beat. - **`create_decks`** — DJ-style A/B decks blended by a master crossfader (Cross TOP) with per-deck gain; each deck pulls a source TOP or a built-in test source (CLI `decks`). - **`detect_pitch`** (experimental) — monophonic pitch (Hz / MIDI note) from the FFT's dominant bin on a Null CHOP, for melody-reactive parameters (CLI `pitch`). - **`learn_control`** (experimental) — interactive MIDI/OSC "learn": snapshot an input CHOP, then bind the control the artist just moved (CLI `learn`). - **`render_output`** — save a TOP to an image file at its native, full resolution (PNG/JPG/EXR/TIFF), for exporting finished frames — unlike get_preview's small inline thumbnail. - **`optimize_performance`** — scan a network for cook-time bottlenecks and report the slowest nodes with a concrete suggestion each; with apply:true, lower the flagged TOPs' resolution to reclaim GPU time. - **`diff_snapshots`** — compare two snapshot_td_graph snapshots and return a readable diff: nodes added/removed, connection changes, and per-node parameter changes (before/after) — for versioning a patch or seeing exactly what an edit changed. Pure, offline analysis. - **`list_recipes` / `apply_recipe`** — browse the built-in recipe library and instantiate a recipe by id in one call. - **Keyboard / gamepad / mouse input** in `create_external_io` (`keyboard_in`, `gamepad_in`, `mouse_in`) — more control sources to bind to parameters. - **CLI commands** `render`, `optimize`, `diff`, `recipes` and `recipe`. - **`search_operators`** — keyword search over the embedded 629-operator knowledge base, ranked by relevance and fully offline, so the assistant can find the right operator ('what sends DMX?') instead of guessing a type. (Relevance ranking over names/descriptions/keywords — no embedding dependency.) - **`document_network`** — read an existing network and return a readable map: counts by operator family/type plus a Mermaid flowchart of the data flow, for explaining or handing off a patch. - **AI prompts**: `image_to_visual` (recreate a reference image's look in real nodes — multimodal), `tweak_visual` (plain-language adjustments → the right parameters), `critique_visual` (aesthetic + performance critique with concrete fixes), `vj_set_builder` (assemble a full reactive set), and `fix_shader` (diagnose a GLSL TOP compile error against TD's conventions). - **CLI commands** `operators` and `document`. - **`create_layer_mixer`** — a VJ layer mixer: 'crossfade' makes an A/B Cross TOP with a Crossfade knob, or composite inputs with a blend mode (add/difference/hardlight/glow/…). Sources come in via Select TOPs so they can live anywhere. - **`create_video_player`** — a Movie File In player, or a playlist of clips through a Switch TOP, with live Play / Speed (and Clip) controls. - **`create_3d_scene`** — a renderable 3D scene (Geometry + Camera + Light + Render TOP) for a sphere/box/grid, with RotateY (spin) and Zoom knobs. - **`create_projection_mapping`** — wrap a source in a Corner Pin warp; drag the four handles to fit a physical surface, output ready for setup_output. - **`create_keyframe_animation`** — animate parameters along a keyframed curve (time/value keys, linear or smooth easing), looping and synced to the timeline — choreographed motion beyond the animate_parameter LFO. - **`create_simulation`** — GPU simulations: 'reaction_diffusion' (Gray-Scott, via the recipe) plus 'slime' and 'fluid' feedback flow-field looks, with a Decay knob. - **CLI commands** `mixer`, `video`, `scene3d`, `mapping`, `keyframe` and `simulation`. - **`manage_cue`** — a scene system: store / recall / list / delete named cues (snapshots of a COMP's custom parameters) and, crucially, **`morph`** to a cue — a timed, eased crossfade of every numeric control from the current look to the cue (via a small Execute DAT), so you can glide between looks instead of hard-cutting. - **`create_macro`** — one macro knob (0–1) that drives many parameters at once, each remapped into its own [min,max] with an optional response curve — sweep a whole look from one fader. - **`randomize_controls`** — randomize a COMP's numeric controls within their ranges, with an `amount` that blends toward random (a gentle nudge or a full scramble) — instant variations for improvisation. Non-numeric controls are left untouched. - **`create_control_surface`** — build a playable panel (a Container COMP of widgets): vertical faders that drive parameters and buttons that recall or morph to cues. Open it in Perform mode for a touchable stage surface. - **`create_phone_remote`** — serve a mobile web panel from a Web Server DAT: open a URL on your phone and every numeric control becomes a touch slider, no app to install. (Trusted networks only — it accepts writes without auth, like the bridge.) - **OSC / MIDI output** in `create_external_io` (`osc_out`, `midi_out`) — send a CHOP's channels back out for bidirectional feedback to lighting desks, other apps or hardware. - **CLI commands** `cue`, `macro`, `randomize`, `surface` and `remote` for the above. - **`extract_audio_features`** — build an audio-analysis chain that exposes ready-to-bind reactive channels (overall level plus bass/mid/treble band energies) on a Null CHOP, with a Sensitivity knob. Source can be the live device (mic/line), an audio file, a synthetic oscillator (for testing without device permission), or an existing CHOP. - **`create_tempo_sync`** — a Beat CHOP clock driven by TouchDesigner's global tempo, exposing beat-synced channels (`ramp`, `pulse`, `count`, `beat`, `bar`, `bpm`). With `emit_events` on, a CHOP Execute DAT broadcasts a **`beat` event** over the bridge WebSocket on every beat, so `tdmcp-agent watch` and the AI can react to the pulse live. - **`bind_to_channel`** — the link that makes a visual react: drive any node parameter from a CHOP channel (an audio feature or a beat channel) by expression, with a scale and offset. Wires `extract_audio_features` / `create_tempo_sync` into a visual system. - **`beat_reactive_designer` prompt** — guides the assistant through building the reactive chain and mapping audio features / the beat onto a visual system's parameters. - **CLI commands** `audio-features`, `tempo-sync` and `bind` for the above. - **`reload_bridge`** — hot-reload the bridge's Python inside the running TouchDesigner so edits under `td/` take effect without reopening the project (also `tdmcp-agent reload`). - **`manage_checkpoint`** — store / restore / list / delete a full snapshot of a sub-network (an "undo point"). A checkpoint captures every node's constant parameters, the wiring and node positions; restoring reapplies parameters, recreates nodes deleted since (with their wiring) and prunes nodes created since. Complements `manage_presets` (which captures custom-parameter looks for performance) by snapshotting the whole network. - **CLI `preview`** — capture a TOP straight to a PNG file (`-o/--out`). - **CLI `watch`** — stream TouchDesigner bridge events (`node.created`, `node.cook`, `timeline.frame`, …) as ndjson until interrupted; `--include-high-frequency` opts into the per-frame events. - **CLI: full Layer-1/Layer-2 coverage** — the agent now exposes the high-level generators and building blocks, not just Layer-3 CRUD: `visual`, `feedback`, `generative`, `particles`, `audio-reactive`, `dataviz`, `post-fx`, `output`, `plan`, plus `animate`, `arrange`, `connect`, `container`, `control-panel`, `io`, `glsl`, `chain`, `script`, `duplicate`, `component`, `preset`, `params` and `checkpoint`. Whole systems can now be scripted from a shell. - **Obsidian vault integration** — bridge a folder of Markdown notes (set `TDMCP_VAULT_PATH`) and TouchDesigner, with path-traversal-safe IO and frontmatter parsing: `scaffold_vault` (a starter vault layout with worked examples), `save_recipe_to_vault` (capture a live network as a recipe note, merged into the recipe library), `apply_shader_from_vault` (build a GLSL TOP from a fenced-`glsl` note), `sync_presets_vault` (presets ↔ Markdown), `export_network_to_vault` (a Mermaid + `[[wikilink]]` patch map), `log_performance` (a dated show diary with snapshot + thumbnail), `import_setlist` (build a show from a setlist note's `tracks`), `bind_vault_text` (a Text DAT live-synced to a note) and `generate_from_moodboard` (seed `create_generative_art` from a palette/mood note). ### Changed - **`create_3d_scene` instancing** — an `instances` param scatters N copies of the geometry over a grid via GPU instancing, with the camera framed to fit. `scale_variation` (0–1) gives each copy a random size via a per-point `pscale` attribute, and `spin` (deg/sec) rotates each copy over time through an `instancery` expression (validated live: a 3×3 grid renders with varied scale + spin). - **`search_operators` semantic mode** — opt-in `semantic: true` re-ranks keyword candidates by embedding similarity through the configured LLM endpoint (`TDMCP_LLM_BASE_URL`/`_MODEL`), falling back to keyword ranking when unavailable. Candidate embeddings are cached in-memory (keyed by model, LRU-bounded), so within a session repeat searches only embed the new query, not the whole candidate pool. The default stays pure keyword (zero-config); for best results point `TDMCP_LLM_MODEL` at a dedicated embedding model (e.g. `nomic-embed-text`). [0.3.0]: https://github.com/Pantani/tdmcp/releases/tag/v0.3.0 ## [0.2.0] - 2026-05-26 Live control: generated systems are now playable instruments, not just static renders. ### Added - **`create_control_panel`** — append custom parameters (sliders, toggles, menus, RGB, pulse) to a COMP and bind them to node parameters, so a generated system gets real knobs. - **`animate_parameter`** — drive one or more parameters over time with an LFO (sine/triangle/ramp/square/pulse/random) between a min and max — movement without manual keyframing. - **`manage_presets`** — store / recall / list / delete named snapshots of a COMP's parameter values, saved in the COMP's storage so they persist with the project. - **`create_external_io`** — bridge to the outside world: OSC input and MIDI input mapped straight to parameters (control surfaces), DMX/Art-Net output for lighting, and NDI / Syphon-Spout video input. - **`manage_component`** — save any COMP as a reusable `.tox` file and load it back, as an independent copy or a live-linked instance. - **Auto-exposed control panels** on the artist generators: `create_feedback_network` (Feedback), `create_particle_system` (Drag/Turbulence/Gravity/Lifetime), `create_generative_art` (Speed), `create_audio_reactive` (Sensitivity) and `create_data_visualization` (Scale). Every generator now arrives playable. Pass `expose_controls: false` to opt out. - **Recipe `controls`** field — recipes can declare a control panel (bind targets use recipe node names; they are resolved to real paths on build), plus a new **`performable_feedback_tunnel`** recipe that ships with Feedback/Zoom/Spin/Blur knobs. - **Recursive `get_td_performance`** — measures cook time across the whole sub-network (including nested generated containers), returns the slowest nodes first, and is recursive by default. ### Fixed - `create_feedback_network`'s `feedback_gain` was a silent no-op (it set a non-existent `gain` parameter on a Level TOP); it now sets `brightness1`, so the loop actually decays. [0.2.0]: https://github.com/Pantani/tdmcp/releases/tag/v0.2.0