Fountain Coach Gitowner-controlled · read only

teatro-codex-macos-prompt-field-guide.git · openapi.yaml

teatro-codex-macos-prompt-field-guide.git / openapi.yaml

revision 1a997561baff998149fa4cac8822cfa2b4a9ba75 · complete file

openapi: 3.1.0
info:
  title: Teatro Prompt Language API
  version: 1.0.0
  description: |
    One-file OpenAPI spec that expresses the Teatro prompt language as data schemas
    and a small set of operations for validation, rehearsal, comparison, and merge.
    This represents the DSL as structured JSON rather than the symbolic notation.

    Source reference: README, parts/ (01–16), quick-reference, examples.
servers: []
paths:
  /validate:
    post:
      summary: Validate a Teatro score document
      operationId: validateScore
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TeatroScore'
            examples:
              richScore:
                $ref: '#/components/examples/RichScore'
      responses:
        '200':
          description: Validation result
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        path: { type: string }
                        message: { type: string }
                required: [ok, errors]

  /render:
    post:
      summary: Normalize a Teatro score (e.g., expand symbols to canonical values)
      operationId: renderScore
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                score: { $ref: '#/components/schemas/TeatroScore' }
                options:
                  type: object
                  properties:
                    expandSymbols: { type: boolean, default: true }
                    compactLayers: { type: boolean, default: false }
              required: [score]
      responses:
        '200':
          description: Normalized score
          content:
            application/json:
              schema:
                type: object
                properties:
                  score: { $ref: '#/components/schemas/TeatroScore' }
                  normalized: { type: boolean }
                required: [score, normalized]

  /rehearse:
    post:
      summary: Apply meta-commands (conductor directives) to a score
      operationId: rehearseScore
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                score: { $ref: '#/components/schemas/TeatroScore' }
                directives:
                  type: array
                  items: { $ref: '#/components/schemas/MetaCommand' }
              required: [score, directives]
      responses:
        '200':
          description: Result after applying directives
          content:
            application/json:
              schema:
                type: object
                properties:
                  score: { $ref: '#/components/schemas/TeatroScore' }
                required: [score]

  /merge:
    post:
      summary: Merge two scores
      operationId: mergeScores
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                a: { $ref: '#/components/schemas/TeatroScore' }
                b: { $ref: '#/components/schemas/TeatroScore' }
                strategy:
                  type: string
                  enum: [prefer_a, prefer_b, interleave]
                  default: interleave
              required: [a, b]
      responses:
        '200':
          description: Merged score
          content:
            application/json:
              schema:
                type: object
                properties:
                  score: { $ref: '#/components/schemas/TeatroScore' }
                required: [score]

  /compare:
    post:
      summary: Compare two scores and return structured differences
      operationId: compareScores
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                a: { $ref: '#/components/schemas/TeatroScore' }
                b: { $ref: '#/components/schemas/TeatroScore' }
              required: [a, b]
      responses:
        '200':
          description: Differences between A and B
          content:
            application/json:
              schema:
                type: object
                properties:
                  diffs:
                    type: array
                    items:
                      type: object
                      properties:
                        path: { type: string }
                        before: {}
                        after: {}
                        note: { type: string }
                required: [diffs]

components:
  schemas:
    TeatroScore:
      type: object
      additionalProperties: false
      properties:
        metadata:
          $ref: '#/components/schemas/ScoreHeader'
        acts:
          type: array
          minItems: 1
          items: { $ref: '#/components/schemas/Act' }
        montage:
          description: Optional cross-scene montage relations at the score level.
          type: array
          items: { $ref: '#/components/schemas/MontageRelation' }
      required: [metadata, acts]
      examples:
        - metadata:
            title: Still Reflection
            version: '1.0'
            date: '2025-10-27'
            palette: calm
            tempo: steady
            register: expressive
            anchor: affect
          acts:
            - title: Awakening
              scenes:
                - title: First Light
                  frames:
                    - id: F1
                      commentary: the window breathes open
                      gesture:
                        tempo: steady
                        light: diffuse
                        motion: [drift]
                        energy: steady
                        durationSeconds: 4
                    - id: F2
                      commentary: attention focuses without rush
                      gesture:
                        tempo: steady
                        light: clear
                        motion: [pulse]
                        energy: rise
                        durationSeconds: 2
                  curtain: baseline
            - title: Resolution
              scenes:
                - title: Return
                  frames:
                    - id: F3
                      commentary: fade to internal stillness
                      gesture:
                        tempo: steady
                        light: partial
                        motion: [breathe]
                        energy: fall
                        durationSeconds: 5
                  curtain: memory

    ScoreHeader:
      type: object
      additionalProperties: false
      properties:
        title: { type: string }
        version: { type: string }
        date: { type: string, format: date }
        palette: { type: string, description: 'Aesthetic palette label (e.g., calm, neutral, contrast)' }
        tempo: { $ref: '#/components/schemas/Tempo' }
        register: { $ref: '#/components/schemas/Register' }
        anchor: { type: string, description: 'Context anchor (e.g., app, stage, affect, narrative, perception, session)' }
        sourceFile: { type: string, description: 'Original filename if imported from textual DSL' }
        originalDsl: { type: string, description: 'Original textual DSL for round-trip preservation' }
        symbolsPreserved: { type: boolean, default: false, description: 'Whether original notation symbols are preserved in symbols blocks' }
      required: [title, version, date, register]

    Act:
      type: object
      additionalProperties: false
      properties:
        id: { type: string }
        title: { type: string }
        rhythm: { $ref: '#/components/schemas/RhythmPattern' }
        scenes:
          type: array
          minItems: 1
          items: { $ref: '#/components/schemas/Scene' }
        montage:
          description: Optional montage relations within this act.
          type: array
          items: { $ref: '#/components/schemas/MontageRelation' }
      required: [title, scenes]

    Scene:
      type: object
      additionalProperties: false
      properties:
        id: { type: string }
        title: { type: string }
        camera:
          $ref: '#/components/schemas/CameraCue'
        rhythm: { $ref: '#/components/schemas/RhythmPattern' }
        frames:
          type: array
          minItems: 1
          items: { $ref: '#/components/schemas/Frame' }
        curtain:
          $ref: '#/components/schemas/CurtainType'
        transitions:
          description: Transitions linking frames within the scene.
          type: array
          items: { $ref: '#/components/schemas/Transition' }
      required: [title, frames]

    Frame:
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          pattern: '^F[0-9]+$'
        gesture:
          $ref: '#/components/schemas/Gesture'
        mood: { type: string }
        focus: { type: string }
        commentary: { type: string }
        camera:
          $ref: '#/components/schemas/CameraCue'
        layers:
          type: array
          items: { $ref: '#/components/schemas/Layer' }
        meta:
          type: array
          items: { $ref: '#/components/schemas/MetaCommand' }
        register: { $ref: '#/components/schemas/Register' }
        tags:
          type: array
          items: { type: string }
        annotations:
          type: array
          items: { $ref: '#/components/schemas/Annotation' }
        symbols:
          $ref: '#/components/schemas/NotationSymbols'
        transitions:
          description: Optional per-frame transitions to other frames.
          type: array
          items: { $ref: '#/components/schemas/Transition' }
      required: [id, gesture]

    Layer:
      type: object
      additionalProperties: false
      properties:
        name: { type: string }
        gestures:
          type: array
          minItems: 1
          items: { $ref: '#/components/schemas/Gesture' }
        register: { $ref: '#/components/schemas/Register' }
      required: [name, gestures]

    Gesture:
      type: object
      additionalProperties: false
      properties:
        tempo: { $ref: '#/components/schemas/Tempo' }
        light: { $ref: '#/components/schemas/Light' }
        motion:
          type: array
          items: { $ref: '#/components/schemas/MotionVerb' }
        energy: { $ref: '#/components/schemas/EnergyCurve' }
        durationSeconds:
          type: number
          minimum: 0
        timing:
          $ref: '#/components/schemas/Timing'
        operators:
          type: array
          items: { $ref: '#/components/schemas/OperatorInstruction' }
        register: { $ref: '#/components/schemas/Register' }
        tags:
          type: array
          items: { type: string }
        annotations:
          type: array
          items: { $ref: '#/components/schemas/Annotation' }
        symbols:
          $ref: '#/components/schemas/NotationSymbols'
      required: [tempo, light]

    OperatorInstruction:
      type: object
      additionalProperties: false
      properties:
        operator: { $ref: '#/components/schemas/Operator' }
        target:
          type: string
          enum: [light, motion, tempo, camera, energy]
        factor:
          type: number
          description: Scalar like @2x or 0.5 for softening
        notes: { type: string }
        timing:
          $ref: '#/components/schemas/Timing'
        scope:
          $ref: '#/components/schemas/Scope'
        order:
          type: integer
          minimum: 0
      required: [operator]

    CameraCue:
      type: object
      additionalProperties: false
      properties:
        path:
          type: array
          items: { $ref: '#/components/schemas/CameraFraming' }
          minItems: 1
        lensFNumber:
          type: number
          minimum: 1.2
          maximum: 22
        focusMode:
          type: string
          enum: [rack, pull, lock]
        move:
          $ref: '#/components/schemas/CameraMove'
        keyframes:
          description: Camera keyframes over the frame timeline (0..1).
          type: array
          items: { $ref: '#/components/schemas/CameraKeyframe' }

    MetaCommand:
      type: object
      additionalProperties: false
      properties:
        type:
          type: string
          enum: [
            focus_on_stage,
            rehearse_variant,
            freeze_frame,
            restore_frame,
            shift_register,
            compress_timeline,
            expand_timeline,
            wipe_stage
          ]
        params:
          type: object
          additionalProperties: true
          properties:
            frameId: { type: string }
            toRegister: { $ref: '#/components/schemas/Register' }
            factor: { type: number }
      required: [type]

    Tempo:
      type: string
      enum: [steady, moderate, quick, still]
      description: '♩ steady · ♪ moderate · ♬ quick · 𝄐 still'

    Light:
      type: string
      enum: [clear, diffuse, partial, dark]
      description: '☀ clear · ☁ diffuse · 🌒 partial · 🌑 dark'

    MotionVerb:
      type: string
      enum: [drift, pulse, pivot, collapse, unfold, breathe]

    EnergyCurve:
      type: string
      enum: [rise, fall, delay_resolve, oscillate, steady]
      description: '∧ rise · ∨ fall · S delay→resolve · ~ oscillate · — steady'

    Operator:
      type: string
      enum: [amplify, soften, invert, dissolve, echo, sharpen, blur, mirror, merge, split, hybrid]
      description: '↑ amplify · ↓ soften · ¬ invert · ⊹ dissolve · ∿ echo · ⧉ sharpen · ◌ blur · ↔ mirror · ⊕ merge · ⊖ split · ⊛ hybrid'

    CameraFraming:
      type: string
      enum: [WS, MS, CU, POV, OTS]

    CameraMove:
      type: string
      enum: [pan, tilt, zoom, dolly, orbit]

    CutType:
      type: string
      enum: [match, cross_fade, jump, dissolve]

    TransitionType:
      type: string
      enum: [forward, recall, dialogue, loop, crossfade, cut]

    CurtainType:
      type: string
      enum: [baseline, memory, unresolved]

    Register:
      type: string
      enum: [technical, expressive, psychological]

  examples:
    RichScore:
      summary: Rich example with transitions, montage, camera keyframes, and operators
      value:
        metadata:
          title: Focus Reveal
          version: '1.0'
          date: '2025-10-27'
          palette: neutral
          tempo: steady
          register: expressive
          anchor: perception
          sourceFile: Focus-Reveal.score.teatro
          symbolsPreserved: true
        acts:
          - id: A1
            title: Entry
            rhythm:
              pattern: '1-2-4'
              tokens: [1,2,4]
            scenes:
              - id: S1
                title: Orientation
                camera:
                  path: [WS]
                frames:
                  - id: F1
                    commentary: establish space, low contrast
                    gesture:
                      tempo: steady
                      light: diffuse
                      motion: [drift]
                      energy: steady
                      durationSeconds: 3
                      timing:
                        easing: linear
                    symbols:
                      tempoSymbol: '♩'
                      lightSymbol: '☁'
                      energySymbol: '—'
                transitions:
                  - fromFrameId: F1
                    toFrameId: F2
                    type: forward
                    cut: cross_fade
                    timing:
                      durationSeconds: 0.4
              - id: S2
                title: Attention
                camera:
                  path: [WS, MS, CU]
                  keyframes:
                    - { t: 0.0, framing: WS, move: dolly }
                    - { t: 0.6, framing: MS, move: dolly }
                    - { t: 1.0, framing: CU, move: lock }
                frames:
                  - id: F2
                    commentary: accelerate response, brighten foreground
                    gesture:
                      tempo: moderate
                      light: clear
                      motion: [pulse]
                      energy: rise
                      durationSeconds: 2
                      timing:
                        easing: ease_in
                    operators:
                      - operator: sharpen
                        target: light
                        factor: 1.5
                        timing:
                          delaySeconds: 0.2
                        scope:
                          regionName: focus-area
                    annotations:
                      - label: cue
                        value: 'bring attention to primary CTA'
                    symbols:
                      tempoSymbol: '♪'
                      lightSymbol: '☀'
                      energySymbol: '∧'
                transitions:
                  - fromFrameId: F2
                    toFrameId: F3
                    type: forward
                    cut: match
                    timing:
                      durationSeconds: 0.2
              - id: S3
                title: Engage
                camera:
                  path: [CU]
                frames:
                  - id: F3
                    commentary: settle into detail, sharpen edges
                    gesture:
                      tempo: steady
                      light: clear
                      motion: []
                      energy: steady
                      durationSeconds: 2
                    operators:
                      - operator: amplify
                        target: light
                        factor: 1.2
                      - operator: mirror
                        target: motion
                        notes: 'subtle UI echo on secondary panel'
                curtain: baseline
            montage:
              - fromSceneId: S1
                toSceneId: S2
                relation: contrast
                cut: cross_fade
                rhythm:
                  pattern: 'contrast'
              - fromSceneId: S2
                toSceneId: S3
                relation: echo
                cut: match

    # New schemas for full parity with the Teatro DSL
    Timing:
      type: object
      additionalProperties: false
      properties:
        durationSeconds: { type: number, minimum: 0 }
        delaySeconds: { type: number, minimum: 0 }
        loopCount: { type: integer, minimum: 0 }
        easing: { $ref: '#/components/schemas/Easing' }
      description: Timing controls for gestures, operators, and transitions.

    Easing:
      oneOf:
        - type: string
          enum: [linear, ease_in, ease_out, ease_in_out]
        - type: object
          additionalProperties: false
          properties:
            type:
              type: string
              enum: [spring]
            stiffness: { type: number, minimum: 0 }
            damping: { type: number, minimum: 0 }
            mass: { type: number, minimum: 0 }
          required: [type]
      description: Easing curve; either a preset or spring parameters.

    RhythmPattern:
      type: object
      additionalProperties: false
      properties:
        pattern:
          type: string
          description: 'e.g., "1-2-4" or textual label like "contrast|mood"'
        tokens:
          type: array
          items: { type: number }

    Transition:
      type: object
      additionalProperties: false
      properties:
        fromFrameId: { type: string }
        toFrameId: { type: string }
        type: { $ref: '#/components/schemas/TransitionType' }
        cut: { $ref: '#/components/schemas/CutType' }
        timing: { $ref: '#/components/schemas/Timing' }
        notes: { type: string }
      required: [type]

    MontageRelation:
      type: object
      additionalProperties: false
      properties:
        fromSceneId: { type: string }
        toSceneId: { type: string }
        relation:
          type: string
          enum: [contrast, echo, cause, memory]
        cut: { $ref: '#/components/schemas/CutType' }
        rhythm: { $ref: '#/components/schemas/RhythmPattern' }
        notes: { type: string }
      required: [fromSceneId, toSceneId, relation]

    CameraKeyframe:
      type: object
      additionalProperties: false
      properties:
        t:
          type: number
          minimum: 0
          maximum: 1
          description: Normalized time in [0,1] across the frame duration.
        framing: { $ref: '#/components/schemas/CameraFraming' }
        lensFNumber: { type: number, minimum: 1.2, maximum: 22 }
        focusMode: { type: string, enum: [rack, pull, lock] }
        move: { $ref: '#/components/schemas/CameraMove' }

    Annotation:
      type: object
      additionalProperties: false
      properties:
        label: { type: string }
        value: {}
        notes: { type: string }

    Scope:
      type: object
      additionalProperties: false
      properties:
        regionName: { type: string }
        selector: { type: string, description: 'Optional selector for UI region (implementation-defined)' }
        area:
          type: object
          additionalProperties: false
          properties:
            x: { type: number }
            y: { type: number }
            width: { type: number }
            height: { type: number }

    NotationSymbols:
      type: object
      additionalProperties: false
      properties:
        tempoSymbol: { type: string, description: 'e.g., ♩, ♪, ♬, 𝄐' }
        lightSymbol: { type: string, description: 'e.g., ☀, ☁, 🌒, 🌑' }
        energySymbol: { type: string, description: 'e.g., ∧, ∨, S, ~, —' }
        operatorSymbols:
          type: array
          items: { type: string, description: 'e.g., ↑, ↓, ¬, ⊹, ∿, ⧉, ◌, ↔, ⊕, ⊖, ⊛' }