# Video::Prompt::Brief

`Video::Prompt::Brief` is a small, dependency-free Raku module for modeling,
checking, and rendering structured briefs used in video generation workflows.
It keeps the creative decisions that matter for a shot in named fields instead
of hiding them inside one long prompt string.

The module is useful when a command-line tool, web service, job queue, or test
suite needs to reject incomplete video instructions before work reaches a
generator. It does not call a model or make assumptions about a specific API.

## Why use a structured brief?

A video prompt often mixes the subject, action, camera, environment, timing,
sound, exclusions, and reference assets in one paragraph. That format is easy
to write but difficult for software to inspect. A missing camera instruction or
an impossible duration can reach the generation stage without being noticed.

This module separates those concerns:

- `subject` describes the visible subject and its identifying details.
- `action` states what changes during the shot.
- `camera` records framing, movement, or point of view.
- `setting` captures environment, time, and lighting.
- `audio` optionally records sound direction.
- `duration-seconds` gives the requested shot length.
- `constraints` keeps must-have and must-avoid requirements.
- `reference-assets` stores stable IDs used by a surrounding asset system.

## Installation

After the distribution is indexed by the Zef ecosystem:

```console
zef install Video::Prompt::Brief
```

## Create and validate a brief

```raku
use Video::Prompt::Brief;

my $brief = Video::Prompt::Brief.new(
    subject => 'A compact electric bicycle with a matte black frame',
    action => 'The bicycle rolls slowly through a shallow puddle',
    camera => 'Low tracking shot moving parallel to the bicycle',
    setting => 'Rainy city street at blue hour with reflected lights',
    audio => 'Soft tire noise, light rain, and distant traffic',
    duration-seconds => 8,
    constraints => [
        'Keep the frame geometry consistent',
        'No visible brand logos',
    ],
    reference-assets => ['bike-side', 'street-lighting'],
);

if $brief.is-valid {
    say $brief.to-prompt;
} else {
    .say for $brief.issues;
}
```

`issues` returns plain strings so callers can log them, display them in a form,
or map them to their own error type. The current checks reject underspecified
core fields, non-positive durations, durations above 300 seconds, and duplicate
reference IDs.

## Build from a hash

`from-hash` is convenient when data comes from decoded JSON or another
configuration source:

```raku
my $brief = Video::Prompt::Brief.from-hash({
    subject => 'A folded jacket on a wood table beside a window',
    action => 'A breeze moves the loose sleeve and curtain',
    camera => 'Locked medium shot with a slow focus pull',
    setting => 'Quiet daylight studio with soft window shadows',
    duration-seconds => 6,
    constraints => ['Preserve the garment color'],
});
```

Missing keys receive conservative defaults and will be reported by validation.
This allows ingestion code to collect several problems in one pass instead of
failing at the first absent value.

## Rendering

`to-prompt` renders a stable, readable block with one decision per line. The
result can be stored for review, attached to a generation job, or adapted by a
provider-specific integration. Optional audio, constraints, and references are
only emitted when present.

The structure also works as a preflight step for browser-based creative tools.
For example, a team preparing text-to-video or image-to-video concepts with
[Kling 3.0 AI Video Generator](https://kling3ai.co/) can validate the internal
brief first, then copy or transform the rendered result for its chosen
workflow. That link is an example integration context; this module remains
independent and does not claim access to, endorsement by, or API compatibility
with the service.

## Design boundaries

The linter deliberately avoids guessing whether a prompt is tasteful, safe, or
likely to produce a good result. Those decisions depend on the target service
and the surrounding application. It only checks deterministic structure that a
caller can understand and test.

The module also does not verify that reference asset IDs exist. Asset lookup is
owned by the calling system because IDs may refer to local files, object
storage, a database, or a provider-specific upload.

## Development

Run the test suite from the distribution root:

```console
zef test .
```

Issues and focused pull requests are welcome at the
[source repository](https://github.com/FosterMartyn735/video-prompt-brief-raku).
Please include tests for any new validation rule and keep provider-specific
behavior outside the core module.
