Prompt composer and preview (#48) #100

Merged
crowmaki merged 2 commits from issue-48-prompt-composer into main 2026-10-08 21:09:07 +00:00
Owner

Closes #48.

The app writes H3's six-field prompt for every Shot from its current inputs and its filled Slot lists, and shows it read-only on the Shot (User Stories 93–98 and 102–103, decisions in #9). The override and reconcile (#49) and the job builder (#51) read shot_prompt.

What changed

  • Composer (prompt.rs). load gathers a Shot's inputs, and compose is a pure function of those inputs plus the filled ShotSlots. It writes subject_definitions, summary, retention_analysis, detailed_description, overall_soundscape and non_diegetic_music in this order. An empty field is N/A, and music is always N/A. There is exactly one [Shot 1] and no id= header.

  • Tags.

    • <Subject N>: numbered by first appearance in the action text (mentions and dialogue speakers), then the Setup's other subjects, then anyone a Board symbol is about.
    • <Prop N>: numbered in first-mention order, the same order the slot budget attaches Props.
    • <Environment>: the Scene's Location.
    • <Picture N> / <Audio N>: taken from the filled Slot lists, so an excluded or over-budget reference is never named.
    • Character names written into free text (framing note, identity fields, descriptions) become tags. A Character the Shot does not number reads as "someone". Prop names in descriptions stay as written.
  • subject_definitions.

    • Identity fields: the Look's overrides, then the Character's values.
    • Wardrobe: the Look's default wardrobe, or the Wardrobe item's text.
    • Positional Atlas phrasing, with a row name only when the Atlas holds more than one Look. The views are listed per Parity: "face close-up, front and side views".
    • Partial Preservation names the mannequin picture.
    • Heard-only speakers are defined as heard but not seen. A heard-only speaker is a Character outside the Setup whose every Line in the Shot is O.S./O.C. or V.O.
    • A Voice reference adds "uses as 's speaking voice timbre reference". This repeats the tag instead of #9's "their", because the ticket rules out pronouns.
    • <Environment> is the description, then the lighting note (the set note, else the Lighting's phrase), then "shown in". <Prop N> is the description, then "shown in".
  • retention_analysis. One entry per sent image, in wired order, per the spec table:

    • Keyframe first frame and last frame. The last frame time is the Shot's length on the frame grid.
    • An Atlas row, full or partial.
    • The mannequin's attribute_transfer.
    • The location angle.
    • A Board weak_reference: tiled or one picture per Panel. A clean-sketch Board drops the arrows clause.
    • A Prop.

    Then newly_generated for every seen subject whose Atlas row is not sent, then one entry per Voice reference.

  • detailed_description. The framing note, then the Notation read-backs as sentences in panel order (no "storyboard" or "panel" wording, and freehand arrows add nothing), then the action text. Dialogue chips expand as follows:

    • Each chip becomes <Subject N> says: <d>[Language] <tag> text</d>, with parentheticals as inline tags.
    • O.S./O.C. becomes "says from off-screen:", and V.O. becomes "says in voice-over:".
    • Dual dialogue is announced once: "… speak at the same time."
    • A SUBTITLE Line uses its own language and spoken text.
    • Character-naming parentheticals are already moved out of the quote by the action text (#46).
  • overall_soundscape. The Location's Ambience plus the Scene's Ambience addition, written as one sentence.

  • Schema v20.

    • project.spoken_language: defaults to English, and a blank value is refused.
    • scene.ambience_addition.

    Both have undoable setters (set_spoken_language, set_scene_ambience) and are on ProjectView/SceneView and their DTOs. CONTEXT.md now defines Spoken language and notes the Scene addition under Ambience.

  • Adapter. shot_prompt, set_spoken_language and set_scene_ambience are new commands, and the bindings are regenerated.

  • UI.

    • A collapsible Prompt panel on each Shot shows the composed text read-only. It loads when opened and follows changed events while open.
    • Scenes view: an Ambience addition field.
    • Project properties: a Spoken language field.

Tests

  • tests/prompt_composer.rs (11 tests, all through ProjectSession):
    • Exact full-prompt text for a bare Shot and for a fully referenced Shot (Atlas, location angle, Board, Prop, both Keyframes, two voices).
    • Multi-row Atlas phrasing.
    • Wardrobe partial Preservation and attribute transfer, including the mannequin sent without its Atlas.
    • Slot renumbering when items are excluded.
    • Board read-backs and the tiled, per-Panel and clean variants.
    • V.O., dual dialogue, a moved parenthetical, the SUBTITLE language and the Project language.
    • The summary fallback.
    • The undoable Scene Ambience addition.
    • "someone" for an unnumbered Character.
  • The adapter smoke test covers the three new commands.
  • notation.rs's schema rewind drops the two new columns.
  • Results: cargo test --workspace --all-features, bun test src (123) and svelte-check all pass. Clippy shows only the existing type_complexity warning in api.rs.

Notes for review

  • I did not open the preview in the running app.
Closes #48. The app writes H3's six-field prompt for every Shot from its current inputs and its filled Slot lists, and shows it read-only on the Shot (User Stories 93–98 and 102–103, decisions in #9). The override and reconcile (#49) and the job builder (#51) read `shot_prompt`. ## What changed - **Composer** (`prompt.rs`). `load` gathers a Shot's inputs, and `compose` is a pure function of those inputs plus the filled `ShotSlots`. It writes `subject_definitions`, `summary`, `retention_analysis`, `detailed_description`, `overall_soundscape` and `non_diegetic_music` in this order. An empty field is `N/A`, and music is always `N/A`. There is exactly one `[Shot 1]` and no `id=` header. - **Tags.** - `<Subject N>`: numbered by first appearance in the action text (mentions and dialogue speakers), then the Setup's other subjects, then anyone a Board symbol is about. - `<Prop N>`: numbered in first-mention order, the same order the slot budget attaches Props. - `<Environment>`: the Scene's Location. - `<Picture N>` / `<Audio N>`: taken from the filled Slot lists, so an excluded or over-budget reference is never named. - Character names written into free text (framing note, identity fields, descriptions) become tags. A Character the Shot does not number reads as "someone". Prop names in descriptions stay as written. - **subject_definitions.** - Identity fields: the Look's overrides, then the Character's values. - Wardrobe: the Look's default wardrobe, or the Wardrobe item's text. - Positional Atlas phrasing, with a row name only when the Atlas holds more than one Look. The views are listed per Parity: "face close-up, front and side views". - Partial Preservation names the mannequin picture. - Heard-only speakers are defined as heard but not seen. A heard-only speaker is a Character outside the Setup whose every Line in the Shot is O.S./O.C. or V.O. - A Voice reference adds "uses <Audio N> as <Subject N>'s speaking voice timbre reference". This repeats the tag instead of #9's "their", because the ticket rules out pronouns. - `<Environment>` is the description, then the lighting note (the set note, else the Lighting's phrase), then "shown in". `<Prop N>` is the description, then "shown in". - **retention_analysis.** One entry per sent image, in wired order, per the spec table: - Keyframe first frame and last frame. The last frame time is the Shot's length on the frame grid. - An Atlas row, full or partial. - The mannequin's `attribute_transfer`. - The location angle. - A Board `weak_reference`: tiled or one picture per Panel. A clean-sketch Board drops the arrows clause. - A Prop. Then `newly_generated` for every seen subject whose Atlas row is not sent, then one entry per Voice reference. - **detailed_description.** The framing note, then the Notation read-backs as sentences in panel order (no "storyboard" or "panel" wording, and freehand arrows add nothing), then the action text. Dialogue chips expand as follows: - Each chip becomes `<Subject N> says: <d>[Language] <tag> text</d>`, with parentheticals as inline tags. - O.S./O.C. becomes "says from off-screen:", and V.O. becomes "says in voice-over:". - Dual dialogue is announced once: "… speak at the same time." - A SUBTITLE Line uses its own language and spoken text. - Character-naming parentheticals are already moved out of the quote by the action text (#46). - **overall_soundscape.** The Location's Ambience plus the Scene's Ambience addition, written as one sentence. - **Schema v20.** - `project.spoken_language`: defaults to English, and a blank value is refused. - `scene.ambience_addition`. Both have undoable setters (`set_spoken_language`, `set_scene_ambience`) and are on `ProjectView`/`SceneView` and their DTOs. CONTEXT.md now defines Spoken language and notes the Scene addition under Ambience. - **Adapter.** `shot_prompt`, `set_spoken_language` and `set_scene_ambience` are new commands, and the bindings are regenerated. - **UI.** - A collapsible **Prompt** panel on each Shot shows the composed text read-only. It loads when opened and follows `changed` events while open. - Scenes view: an **Ambience addition** field. - Project properties: a **Spoken language** field. ## Tests - `tests/prompt_composer.rs` (11 tests, all through `ProjectSession`): - Exact full-prompt text for a bare Shot and for a fully referenced Shot (Atlas, location angle, Board, Prop, both Keyframes, two voices). - Multi-row Atlas phrasing. - Wardrobe partial Preservation and attribute transfer, including the mannequin sent without its Atlas. - Slot renumbering when items are excluded. - Board read-backs and the tiled, per-Panel and clean variants. - V.O., dual dialogue, a moved parenthetical, the SUBTITLE language and the Project language. - The summary fallback. - The undoable Scene Ambience addition. - "someone" for an unnumbered Character. - The adapter smoke test covers the three new commands. - `notation.rs`'s schema rewind drops the two new columns. - Results: `cargo test --workspace --all-features`, `bun test src` (123) and `svelte-check` all pass. Clippy shows only the existing `type_complexity` warning in `api.rs`. ## Notes for review - I did not open the preview in the running app.
Compose H3's six-field prompt for a Shot from its current inputs and its
filled Slot lists: subject definitions with positional Atlas phrasing and
Preservation, retention entries per the spec table, Notation read-backs as
plain directions, quoted dialogue with language, delivery and inline tags,
and the Location's Ambience plus the Scene's addition as the soundscape.
Nothing is named: Characters, Props and the Location are tags, and slot
tags count only what is sent.

Adds the Project's spoken language and a Scene's Ambience addition, both
undoable, and a read-only prompt preview on each Shot.
Repeat the subject tag in the voice timbre phrase, name an Atlas row by a position enum, announce a dual dialogue speaker once, read a cast row by name, define Spoken language in the glossary, and test an outfit sent without its Atlas and an unnumbered Character in free text.
crowmaki deleted branch issue-48-prompt-composer 2026-10-08 21:09:07 +00:00
Sign in to join this conversation.
No description provided.