Skip to content

Add ftrack and ShotGrid note push - #27

Open
emlcpfx wants to merge 2 commits into
D-Mad:mainfrom
emlcpfx:pr5-tracker-notes
Open

emlcpfx wants to merge 2 commits into
D-Mad:mainfrom
emlcpfx:pr5-tracker-notes

Conversation

@emlcpfx

@emlcpfx emlcpfx commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

File > Push Notes to Tracker... sends this source's comments to ftrack or ShotGrid as review notes.

Drawings are not pushed — a tracker note is words, and a scribble without the frame under it says nothing. The annotated frames go up via the PDF report (#26) or the image export instead.

The ftrack mapping was checked against a live instance, not guessed

I pulled the real Note schema from a live ftrack instance rather than inferring it from the docs, and two things it revealed would otherwise have been wrong:

  • frame_number is a native integer field on Note. ftrack anchors notes to a frame itself. FrameDeck's per-frame comments therefore map straight onto it. The obvious guess — encoding the frame into the note text — would have thrown away the one thing that makes the note reviewable in place, and it would have looked like it worked.
  • user_id is REQUIRED. A note cannot be posted anonymously. The author is now resolved from the session up front, so a bad configuration fails immediately rather than being rejected server-side with half the notes already in flight.

tests/data/ftrack_note_schema.json is a snapshot of that live schema, and test_every_ftrack_field_we_send_exists_on_the_live_schema pins every field we send against it. An invented field name can no longer reach a server.

Other mappings that fall out of the real schema:

FrameDeck ftrack
comment text content
frame frame_number (native)
done is_todo — arrives as a completed to-do, not an open note an artist has to triage again
comment id metadata — so re-pushing a shot updates existing notes instead of littering the tracker with duplicates

ShotGrid is NOT validated against a live site

Stated plainly in its module docstring, because the difference matters. It follows the documented shotgun_api3 Note entity, but nobody has run it against a real ShotGrid.

The known structural difference: ShotGrid's Note has no frame field at all. Frame-accurate notes there live on Version annotations, which is a much larger integration. So the frame is carried in the note subject and body, where a human will actually read it. If you want true frame-anchored ShotGrid notes, that's a separate and considerably bigger piece of work.

Testing without a server

Both trackers take an injected session, so the mapping is exercised against a fake client — no server, no credentials, no network. 18 tests cover the payloads, the required-author failure, duplicate suppression on re-push, an edited comment updating in place, a rejected commit rolling the session back (a dirty session would poison the next push), and "push nothing" not touching the server at all.

Credentials are read from the standard environment variables by the APIs themselves (FTRACK_SERVER / FTRACK_API_USER / FTRACK_API_KEY, SHOTGRID_SITE / SHOTGRID_SCRIPT_NAME / SHOTGRID_API_KEY). FrameDeck never stores or handles them, and the dialog never asks for them — it only asks what the tracker cannot know: which entity the notes belong to.

ftrack_api and shotgun_api3 are imported lazily and are optional: FrameDeck starts fine without either.

Verification status — read this before merging

  • ftrack field mapping: verified against a live instance's schema.
  • ftrack round-trip (notes actually landing): NOT run. No note was ever created on a real tracker — that's a production write and it wasn't mine to make. Someone with an instance should push to a test AssetVersion once before this is trusted in anger.
  • ShotGrid: mock-tested only, unvalidated, as above.

256 tests on the branch, compile clean. Branches off current main.

emlcpfx and others added 2 commits July 14, 2026 15:39
File > Push Notes to Tracker... sends this source comments to ftrack or
ShotGrid as review notes. Drawings are not pushed: a tracker note is words,
and a scribble without the frame under it says nothing. The annotated frames
go up via the PDF report or the image export instead.

The ftrack field mapping was checked against a live ftrack instance Note
schema, not inferred from the docs, and two things it revealed would otherwise
have been wrong:

- frame_number is a NATIVE integer field on Note. ftrack anchors notes to a
  frame itself, so FrameDeck per-frame comments map straight onto it. The
  obvious guess, encoding the frame into the note text, would have thrown away
  the one thing that makes the note reviewable in place.
- user_id is REQUIRED. A note cannot be posted anonymously, so the author is
  resolved from the session up front. Failing there beats a server-side
  rejection with half the notes already in flight.

Resolved comments arrive as completed to-dos (is_todo) rather than as open
notes an artist has to triage again, and FrameDeck comment id is stamped into
Note.metadata so re-pushing a shot updates the existing notes instead of
littering the tracker with duplicates.

tests/data/ftrack_note_schema.json is a snapshot of that live schema, and a
conformance test pins every field we send against it, so an invented field name
can never reach a server.

ShotGrid is NOT validated against a live site and says so in its module
docstring. Its Note entity has no frame field at all (frame-accurate notes live
on Version annotations, a much larger integration), so the frame is carried in
the note subject and body where a human will actually read it.

Both trackers take an injected session, so the mapping is tested against a fake
client with no server, no credentials and no network. Credentials are read from
the standard environment variables by the APIs themselves; FrameDeck never
stores or handles them.

18 tests, 256 on the branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TexnzYbmCjjTDB8zzZuUPb
reviewapp has a working, production-proven ftrack push. Reading it against
this one found a real bug that mock tests could never catch.

In ftrack, is_todo and completion are SEPARATE concerns: is_todo says a note
is actionable, completed_at and completed_by_id say it has been done.
reviewapp sets is_todo True on every note it pushes, and that is right.

This code mapped is_todo to the reviewer done flag, which is backwards and
quietly so:

- an OPEN comment became is_todo False, a plain note nobody is asked to action
- a RESOLVED comment became is_todo True with no completion, landing in the
  artist queue as fresh, uncompleted work

So every note the supervisor had already closed would have arrived as a new
task. Now every note is a to-do, and a resolved one also carries completed_at
and completed_by_id. Re-pushing after resolving closes the ftrack to-do rather
than merely rewording it.

Also follows reviewapp in leading the note body with the clip and frame:
[KP_010_020] F0042  00:00:01:18 - soften this

frame_number is still set, which reviewapp does not do -- it is a real field on
the live schema and it is what lets ftrack anchor a note to a frame in its
player. But it is not relied on: anywhere the field is not surfaced (a notes
list, an email digest), the body still says which frame the note is about.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TexnzYbmCjjTDB8zzZuUPb
@emlcpfx

emlcpfx commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Updated after diffing against reviewapp's production-proven ftrack provider. It caught a real bug that no mock test could have.

is_todo was backwards

In ftrack, is_todo and completion are separate concerns: is_todo means this note is actionable; completed_at / completed_by_id mean it has been done. reviewapp sets is_todo: True on every note it pushes, and that's correct.

This PR originally mapped is_todo to the reviewer's done flag, which is backwards — and quietly so:

FrameDeck comment what it would have become in ftrack
open is_todo=False — a plain comment nobody is asked to action
resolved is_todo=True, never completed — an open to-do in the artist's queue

So every note the supervisor had already closed would have arrived at the artist as fresh work, while the genuinely open ones sat there as passive comments. It would have passed review, passed the mocks, and only surfaced as artists asking why their queue was full of things already fixed.

Now: every note is a to-do, and a resolved one also carries completed_at + completed_by_id. Re-pushing after resolving closes the ftrack to-do rather than just rewording it (test_resolving_a_note_and_repushing_closes_the_ftrack_todo).

Note body now leads with clip and frame

Following reviewapp's proven format:

[KP_010_020] F0042  00:00:01:18 - soften this edge

frame_number is still set — reviewapp doesn't set it, but it's a real field on the live schema and it's what lets ftrack anchor a note to a frame in its player. Crucially it is no longer relied on: anywhere that field isn't surfaced (a notes list, an email digest), the body still says which frame the note is about. Belt and braces rather than a bet on an unproven field.

Remaining difference from reviewapp, deliberately

  • Author field. reviewapp sets author_id; this sets user_id, which is the field the live schema actually declares (and declares as required). Both evidently work — reviewapp is in production — so this is the schema-conformant spelling of the same thing. Worth a second pair of eyes.
  • Thumbnail attachment. reviewapp uploads the rendered annotated frame as a FileComponent and links it via NoteComponent, so the artist sees the drawing next to the note. This PR doesn't — it's a genuinely valuable feature and a self-contained follow-up, but it's a multipart-upload pipeline and I didn't want to bundle it into a note-push PR. Happy to do it next if wanted.

Verification status, restated honestly

  • ftrack field mapping: verified against a live instance's schema, and now cross-checked against a working production implementation.
  • ftrack round-trip: still not run. No note has been created on a real tracker. Someone should push to a throwaway AssetVersion once before this is trusted.
  • ShotGrid: mock-tested only, unvalidated.

257 tests, compile clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant