Feature/review gate frame capture - #46
Merged
ethanfel merged 7 commits intoSep 8, 2026
Merged
Conversation
Adds a "Capture frame..." control to the Review Gate video preview: scrub the native player to a frame, pick or type a tag, and save it as a project asset. Reusing an existing tag appends an incrementing suffix (via the existing _unique_tag logic) so the new capture is recognizable as an updated take of a prior image. Backend: new /project-assets/capture-frame route extracts a single frame with ffmpeg (same -ss/-frames:v pattern as the Plan Studio checkpoint thumbnail builder) and imports it through the existing ProjectAssetStore.import_file path.
The dialog was appended into .h3r-video-panel, which is fixed-height and overflow:hidden — its title and Save/Cancel buttons were being clipped off, leaving only the image, tag field, and hint visible. Anchor it to the widget root instead so it overlays the whole node.
Frame captures reusing an existing tag now read as updated takes of that subject: @char-sammy -> char-sammy1, then char-sammy2, etc., tracking the highest existing suffix in that tag's family. This is deliberately separate from the store's general _unique_tag() (used by uploads/imports/duplicates elsewhere), which keeps its "_2", "_3" ... collision suffix — changing that would ripple into unrelated flows. The capture dialog's tag field is now a text input paired with a small dropdown button that reopens the browser's native <datalist> suggestion list (via showPicker() where supported, a synthetic ArrowDown keydown otherwise), so existing tags can be picked or a new one typed freely.
Scripted attempts to reopen a <datalist> suggestion popup (showPicker() fallback, synthetic keydown) don't work in practice — browsers require a real, trusted user gesture before showing that native UI, so the dropdown button did nothing visible. Replaced it with a small self-drawn list (filtered live as you type, click to fill the tag field) that behaves consistently and stays fully within our control.
The dropdown showing "no tags" with a tag already visible in the Carousel points at a project-name mismatch (Review Gate defaults the capture target to the connected Plan's run_name, which may not be the Carousel project the tag actually lives in) or a silently swallowed fetch error. Show the resolved project name in the dialog and log fetch outcomes to the console so this is diagnosable from the browser devtools instead of guessing blind.
Root cause of the "no tags" report: the capture dialog defaulted its target project to the connected Plan's run_name, but the Asset Carousel's project name is independently editable (e.g. Plan run_name "h3_chain" vs. Carousel project "sammys_house") and can drift from it. Expose _h3ProjectAssetCurrentProject() on the Carousel node so Review Gate can read its actual current project directly, preferring an upstream-connected Carousel and falling back to any Carousel on the canvas, then to the Plan's run_name only if none exists. The dialog's project field is now an editable input (not a static readout) so a wrong guess — or a graph with more than one Carousel — can still be corrected by hand, and changing it re-fetches that project's tags.
Reuses the Carousel's own node._h3ProjectAssetRefresh() (already called elsewhere after uploads/imports) instead of requiring a manual page or node refresh. Only triggers when the on-canvas Carousel is currently showing the same project the frame was just saved to, since refreshing a Carousel pointed at a different project would just reload what it already has.
ethanfel
added a commit
that referenced
this pull request
Sep 7, 2026
Integrate PR #46 with safe project targeting, numbered captures, serialized catalog mutations, and nightly ownership fencing. Preserve deferred review and existing catalog recovery checks. Co-authored-by: Psylenceo <Psylenceo@users.noreply.github.com>
ethanfel
added a commit
that referenced
this pull request
Sep 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
char-sammy) saves the capture as an updated take with a bare incrementing suffix (char-sammy1,char-sammy2, ...) instead of colliding, so both stay visible in the Carousel.run_name) via a small new accessor on the Carousel node, and lets you override it by hand if needed.Implementation
POST /minimax_h3_context_loop/project-assets/capture-frameroute (chain_nodes.py). Extracts a single frame with ffmpeg using the same-ss/-frames:vpattern as the existing Plan Studio checkpoint-thumbnail builder, then imports it through the existingProjectAssetStore.import_file()path (same as uploads/imports).project_assets.py: new_capture_family_tag()/ProjectAssetStore.resolve_capture_tag()for the bare-suffix "updated take" numbering, kept separate from the store's existing_unique_tag()(which other flows still use with_2,_3, ... suffixes) so nothing else in the tagging behavior changes.web/h3_chain_review_final.js): "Capture frame..." button and a small dialog (frame preview, editable Carousel-project field, tag field with a custom dropdown of existing tags).web/h3_project_asset_manager.jsgained a one-linenode._h3ProjectAssetCurrentProjectaccessor so Review Gate can read the Carousel's real project instead of guessing from the Plan.Test plan
_capture_family_tag) directly in the project's venv (first reuse ->1, next ->2, re-capturing off an already-numbered tag -> next in the family).