Four critical fixes:
- Remove overflow:hidden on tlRef so Timeline.init's scroll survives re-renders
- Don't call _renderClips() inside mousedown (was destroying event target mid-drag)
- Use refs for undo history to eliminate stale closure in onClipsChanged callback
- Change .tl-clip-area overflow:hidden to overflow:visible so pointer events reach clip edges
Dispatch df:bins-changed custom event from onBinDrop and
AssetContextMenu.moveToBin so the bin rail counts update
immediately after moving an asset into a bin.
RenameProjectModal is exported to window from screens-projects.jsx,
so Library screen must reference it via window object and use
React.createElement instead of JSX syntax.
- Fix 500 error when creating bins: missing updated_at column on bins table
(migration 013 adds the column, schema.sql updated)
- Add drag-and-drop support for moving asset cards/list rows onto bin rail items
with visual droppable highlight
- Add right-click context menu on project rail items (Rename/Delete)
- Expose RenameProjectModal via window so Library screen can reuse it
- Bins context menu already existed — was hidden by the 500 error
Add 'trim' to job_type enum, create temp_segments table with
expiry/job/asset indexes, and add conform_source_sequence_id
to assets for lineage tracking.
Closes#33
End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api
surfaced four real bugs that made v1.0.0 install cleanly but never load,
plus the missing auth flow. All four are fixed and the panel is verified
connected (status dot green, Reconnect button shown, project list populated).
- manifest.xml: a comment in the <Resources> block contained "--" (inside
"--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec.
CEP 12's strict parser logged
ERROR XPATH Double hyphen within comment
and skipped the panel entirely. Comment rewritten without double hyphens.
- manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest>
and used a non-standard AbstractionLayers/empty <ExtensionList/>
structure. CEP rejected it with
Unsupported Manifest version ''
Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList +
DispatchInfoList + RequiredRuntimeList), matching the working AMPP
panel template.
- main.js: re-declared `const csInterface = new CSInterface()` at top
level even though CSInterface.js already declared the same binding.
CEP 12 shares script-realm lexical scope across <script> tags, so the
second const threw
Identifier 'csInterface' has already been declared
The throw fired before setupEventListeners(), so the Connect button's
click handler was never attached. This is the root cause of the
original "clicking Connect does nothing" symptom; everything else was
secondary. Removed the duplicate declaration; main.js now uses the
binding from CSInterface.js.
- No auth support against AUTH_ENABLED=true servers. mam-api supports
Bearer tokens (POST /api/v1/tokens), so added:
• API token input field (password-masked) next to Server URL
• localStorage persistence on every keystroke
• window.fetch monkey-patch that injects
Authorization: Bearer <token>
on every request whose URL starts with the configured server.
Signed S3 download URLs are NOT touched.
Drive-by fixes that came out of the same debugging pass:
- Server URL input listener was 'change' (fires on blur); switched to
'input' so typing-then-clicking-Connect immediately commits.
- restoreSettings() now strips trailing slashes from the stored URL so
older saved values like 'http://host/' stop producing //api/v1 404s.
- CSS selector `input[type="text"].server-url` didn't match the new
password input → the token field was unstyled and effectively invisible.
Generalized to `input.server-url`; restructured the connection bar into
`.connection-controls--stacked` (flex column) of two `.server-input-row`
rows so two input fields fit cleanly.
- Build scripts now parse ExtensionBundleVersion from both element form
(<ExtensionBundleVersion>X</...>) and attribute form
(ExtensionBundleVersion="X"), since the manifest rewrite switched
schemas.
Version bumped 1.0.0 → 1.0.1. New artifacts committed at
services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB).
v1.0.0 left in place so editors who downloaded it can verify they're on
the broken version.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DELETE /jobs/:id was throwing "404 not found" when the operator tried to
cancel a running job. BullMQ refuses job.remove() while a job is in the
active state; the route caught that error and fell through to the
404 branch, which was misleading because the job actually exists — the
queue was just refusing to drop it from under the worker.
Fix:
- Detect 'active' state explicitly and call moveToFailed(err, '0', false)
first. Token '0' bypasses the per-worker lock check (the operator-side
cancel doesn't hold the worker lock). That transitions active -> failed
and frees the queue's concurrency slot.
- If moveToFailed itself fails (lock owned by a live worker), fall back
to job.discard() so at least the result is thrown away.
- If remove() then fails (stalled, broken state), drop the job's Redis
key directly via queue.client. Last-resort obliteration.
- Stop swallowing getJob() errors — if Redis is sad, surface it via
next(err) instead of returning a misleading 404.
- Return { cancelled: true } when the job was active, so the client
can show "Cancelled" rather than "Removed" in any future toast.
While here: thumbnail jobs now run with concurrency 4 by default
(proxy 2, conform 1, import 1 unchanged). Every queue defaulted to
concurrency 1 before, so a single stalled job blocked the entire queue.
All three are overridable via PROXY_CONCURRENCY / THUMBNAIL_CONCURRENCY
/ CONFORM_CONCURRENCY env vars for nodes with more headroom.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>