diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d860018 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,59 @@ +# Changelog + +All notable **user-visible** changes to H3 Prompt Studio are documented here. +Engineering-only changes (refactors, tests, internal hardening, deployment +posture) are tracked in the dated reports under [`docs/reports/`](docs/reports/). + +This project adheres to [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) +and uses [Semantic Versioning](https://semver.org/). + +## [Unreleased] + +### Added + +- **H3 camera-movement preset chips** in the generation composer — Pan left, + Pan right, Push in, Pull out, Tracking shot, and Static shot. Each chip + inserts its cue at the prompt cursor (replacing a selection, or appending at + the end before the cursor is placed) without disturbing surrounding text, + then the cue-augmented prompt is still validated through the H3 policy + (character limit, duration, ratio, media rules) before submission. Chips are + keyboard-reachable with visible focus and are disabled until every variable is + resolved. (`389ce61`, 2026-07-31) + +## [1.0.0] - 2026-07-31 + +Initial release of H3 Prompt Studio — a self-hostable, single-user workspace +combining a versioned MiniMax H3 video-prompt library with asynchronous H3 +generation jobs. Runs end-to-end with no MiniMax key in deterministic mock mode +and switches to the real server-side API when a key is configured. +(`f41af8c`, 2026-07-31) + +### Added + +- **Versioned prompt library** — title, description, tags, and lifecycle status; + immutable prompt versions; restore-as-new-head; duplicate; archive (never + hard-delete); full-text + tag/status search and filtering. +- **Template engine** — `{{variable}}` placeholders auto-detected into editable + forms, live render preview, and validation of missing variables and render + errors before submission. +- **H3 generation composer** — durations 4–15s, explicit non-adaptive aspect + ratios, `2K`-only resolution, and optional first-frame / last-frame / + reference-image / reference-video / reference-audio URL inputs. +- **Async, idempotent generation jobs** — requests return immediately with a + local job id; `queued → running → succeeded` (or `failed`/`expired`) states + with automatic status refresh; submissions de-duplicated by an idempotency key + (same key + different payload is a conflict). +- **Provider error translation** — provider failures mapped to useful messages + (authentication, balance, moderation, rate-limit, provider) while retaining + the request id; failed/expired jobs retryable as new jobs. +- **Auditable generation history** — each job records the immutable prompt + version, rendered prompt, parameters, provider task id, timestamps, and + outcome. +- **Two providers** — a deterministic mock (seeded sample prompts; success, + failure, expired, provider-error, and slow scenarios) and the real MiniMax H3 + V2 adapter; selected by configuration with no silent fallback to mock. +- **Health endpoint** distinguishing application health from provider + configuration (a missing paid key is reported as `degraded`, not an outage). +- **Production deployment artifacts** — multi-stage Docker image, Docker + Compose, and Kubernetes manifests for namespace `jcode` with persistent + SQLite storage, probes, and non-root hardening. diff --git a/docs/reports/2026-07-31.md b/docs/reports/2026-07-31.md new file mode 100644 index 0000000..57fa7d0 --- /dev/null +++ b/docs/reports/2026-07-31.md @@ -0,0 +1,201 @@ +# Release report — 2026-07-31 + +| Field | Value | +| ---------------- | --------------------------------------------------------------------- | +| Reporting window | 2026-07-24 → 2026-07-31 (UTC), the previous 7 days | +| Generated | 2026-07-31 (UTC) | +| Base branch | `main` | +| Window head | `389ce61` `feat: add H3 camera movement presets` | +| Scope | Default-branch commits and merged changes within the window | +| Pull requests | 2 (Ready, squash-merged): [#8](https://github.com/cnjack/minimax-video-prompt-library/pull/8), [#11](https://github.com/cnjack/minimax-video-prompt-library/pull/11) | + +> This is a documentation-only steward's report. It summarizes what changed and +> does not alter application behavior, dependencies, generated artifacts, or +> deployment settings. It is idempotent for the stated window: regenerating it +> against the same commits reproduces this content. + +## Summary + +This window contains the **initial product release** of H3 Prompt Studio plus one +follow-on feature commit. Three commits landed on `main`, all within the same +~6-hour span on 2026-07-31 (UTC): + +1. The repository brief/PRD and agent profiles were seeded (`7843444`). +2. The complete H3 Prompt Studio vertical slice shipped (`f41af8c`) — the + versioned prompt library, async generation lifecycle, mock + real MiniMax + providers, tests, and production deployment artifacts. +3. The H3 camera-movement preset workflow shipped (`389ce61`), bundled with + prompt/value consistency hardening reviewed adversarially. + +Delivery was mixed. The seed commit (`7843444`) was a **direct commit** to +`main`. The other two changes were delivered as **Ready pull requests** (not +draft) that were **squash-merged** to `main`: H3 Prompt Studio via +[PR #8](https://github.com/cnjack/minimax-video-prompt-library/pull/8) (→ squash +`f41af8c`, merged 2026-07-31T22:41:18Z) and the camera-movement presets via +[PR #11](https://github.com/cnjack/minimax-video-prompt-library/pull/11) (→ squash +`389ce61`, merged 2026-07-31T23:50:19Z). These PR associations come from +**GitHub**, not from commit history: squash-merge commits do not carry PR numbers +in the ordinary `git log`, so commit history alone is not an adequate SCM source +for this window. + +## User-visible changes + +### H3 Prompt Studio — initial release (`f41af8c`) + +- **Versioned prompt library** — create prompts with title, description, tags, + and lifecycle status; immutable versions; restore-as-new-head; duplicate; + archive (never hard-delete); full-text + tag/status search and filtering. +- **Template engine** — `{{variable}}` placeholders with auto-detected, + editable variable forms, live render preview, and validation of missing + variables, blank/unresolved names, and render errors before submission. +- **H3 generation composer** — durations 4–15s, explicit **non-adaptive** aspect + ratios, `2K`-only resolution, and optional first-frame / last-frame / + reference-image / reference-video / reference-audio URL inputs. +- **Async, idempotent generation jobs** — requests return immediately with a + local job id; jobs progress through `queued → running → succeeded` (or + `failed`/`expired`) with automatic status refresh and a visible last-updated + time; submissions are de-duplicated by an idempotency key. +- **Resilient provider error handling** — provider failures are translated into + useful messages (auth, balance, moderation, rate-limit, provider) while + retaining the request id; failed/expired jobs can be retried as new jobs. +- **Auditable history** — each job records the immutable prompt version, the + rendered prompt, parameters, provider task id, timestamps, and outcome. +- **Two providers, one interface** — a deterministic mock (with seeded sample + prompts and success/failure/expired/provider-error/slow scenarios) for + key-less evaluation, and the real MiniMax H3 V2 adapter when a key is + configured (never a silent fallback). +- **Operator surface** — a health endpoint that distinguishes application health + from provider configuration (a missing paid key is `degraded`, not an outage). + +### Camera-movement preset chips (`389ce61`) + +- **One-click H3 camera-motion chips** in the generation composer — **Pan left, + Pan right, Push in, Pull out, Tracking shot, Static shot** — insert their cue + at the prompt cursor (replacing a selection, or appending at the end before + the cursor is placed) without disturbing surrounding text. +- Chips are **keyboard-reachable buttons** with visible focus rings and + accessible motion descriptions; they are **disabled until every variable is + resolved** (a cue in an unresolved prompt would freeze it to only the token). +- The edited prompt mirrors the live render until first touched, then becomes + the source of truth; **Reset to rendered** re-syncs it from the variables. +- The cue-augmented prompt is still validated through the existing H3 request + policy (7000-character limit, duration, ratio, media rules) before submission. + +## Engineering changes + +### Architecture & build (`f41af8c`) + +- pnpm workspace with `shared` / `server` / `client` packages, strict TypeScript + throughout, feature-first modules, and zod runtime schemas as the contract. +- SQLite source of truth with identity (`prompts`) separated from immutable + `prompt_versions` and `generation_jobs`; migrations run on startup and via + `pnpm migrate`. +- **Provider seam** (`VideoProvider` `create`/`query`) isolating MiniMax: the + real H3 V2 adapter (multimodal `content[]`, server-side `Authorization`, + task-state and HTTP-error mapping) and the deterministic mock, tested through + a fake HTTP transport with no paid calls. +- **In-process poller** advances only non-terminal jobs with bounded + retry/backoff; the browser polls the server, never the provider. +- **Concurrency-safe idempotency** — a SQLite unique-key race resolves into + reuse or a 409, never a generic 500; the client keeps its key across transient + failures so a retry cannot create a paid duplicate. +- **Startup orphan recovery** — queued/running jobs with no recorded provider + task are moved to a recoverable `failed` state instead of spinning forever. +- **Security posture** — credentials read server-side only; no logging of + authorization headers or media payloads; inbound request-ids validated against + a bounded safe character set; external URLs validated as `http(s)`. +- **Production artifacts** — multi-stage Docker image (non-root `h3` UID/GID + `10001`), `docker-compose.yml`, and Kubernetes manifests for namespace + `jcode` (Namespace/ConfigMap/PVC/Deployment/Service, probes, `Recreate` + strategy, referenced-but-never-embedded secrets). +- Test suite covering template engine, validation, MiniMax mapping, mock + transitions, repositories, generation service/poller, the core API path, and + high-risk UI states. Verified count: **301 passing** — 84 shared, 43 client, + 174 server (see the validation section below). + +### Camera presets & consistency hardening (`389ce61`) + +- New pure, dependency-free `packages/shared/src/cameraPresets.ts` (labels + + inserted tokens + cursor-aware `insertTokenAtSelection`), exported from the + shared contract and unit-tested. +- `CreateGenerationRequest` gained an optional `prompt` override (trimmed, capped + at `H3_MAX_PROMPT_CHARS`); the generation service **always renders/validates + the immutable version with `values` first**, then uses a non-blank override + verbatim as the final prompt text item — so unresolved variables still fail + before any job or provider call. +- Payload hash and retry now include the `prompt` override, so override-bearing + submissions de-duplicate/retry correctly. +- Composer gains a prompt/value staleness guard: once the prompt is touched, a + later variable edit is flagged and submission is blocked until **Reset to + rendered** re-syncs, preventing recorded `values` from diverging from the + generated text. + +## Risks + +- **Exactly-once boundary (documented, pre-existing)** — the single-instance PoC + stores a job row before submitting to the provider; if interrupted after the + provider accepted but before the task id persisted, the provider may have + started a generation the local row does not know about. Startup recovery + mitigates, but does not eliminate, this gap. +- **New prompt-override surface (`389ce61`)** — a client-authored `prompt` + override is now the generated text. Correctness depends on the new + server-side guard (always render/validate the immutable version with `values` + first, then cap the override). This is brand-new code this week and its risk + is concentrated in `generationService.ts` and the create-generation schema. +- **Single-instance polling** — no durable queue, horizontal multi-instance + polling, or webhooks; acceptable for the PoC, not for prod scale. +- **SSRF / media safety** — external media URLs are validated as `http(s)` only; + URL allowlists and server-side media ingestion are a documented extension + point, not yet implemented. +- **Mutable image tag** — the committed `:latest` Docker tag is a local + convenience; production should pin an immutable tag or digest. + +## Follow-ups + +- Close the exactly-once gap with a **durable outbox plus provider-side + idempotency** (the documented extension point). +- Replace the in-process poller with a **distributed queue** and add + **webhooks**; support **horizontal multi-instance** polling. +- Implement **SSRF allowlists / media scanning** before provider fetches. +- Pin a **digest/tag** for the Kubernetes Deployment instead of `:latest`. +- Revisit the **camera-preset list** if MiniMax guidance expands beyond the + current six motions, keeping the single shared module as the source of truth. +- Consider a version bump (e.g. `1.1.0`) to formally release the camera-preset + feature currently captured under `[Unreleased]` in `CHANGELOG.md`. + +## Validation + +This report is documentation-only; the repository's documented delivery gate was +nonetheless re-run on the window head (`389ce61`) to confirm the documented +quality bar still holds. Exact outcomes: + +| Step | Command | Result | +| ----------- | ---------------------- | ------- | +| Install | `pnpm install` | ✅ ok (372 packages) | +| Lint | `pnpm lint` | ✅ pass — no warnings/errors (exit 0) | +| Type check | `pnpm typecheck` | ✅ pass — shared, server, client strict (exit 0) | +| Tests | `pnpm -r run test` | ✅ **301 passing** (shared 84, client 43, server 174), 0 failing (exit 0) | +| Prod build | `pnpm -r run build` | ✅ pass — shared + server + client (`vite build`, exit 0) | + +No application behavior, dependencies, generated artifacts, or deployment +settings were changed by this report. The working-tree diff is limited to +`CHANGELOG.md` and `docs/reports/2026-07-31.md`; `dist/` and `node_modules` +remain gitignored and are not part of the diff. + +## Source references + +The window has **two Ready pull requests**, both squash-merged to `main`, plus +one direct seed commit. Pull-request numbers are **sourced from GitHub**, not +inferred from `git log` (squash merges do not put PR numbers in ordinary commit +history, so commit history alone is not an adequate SCM source). All three rows +are `main`-branch commits; there are no separate merge commits. + +| Short | Full SHA | Author date (UTC) | Subject | Primary classification | Delivered via | +| --------- | --------------------------------------- | ------------------------ | ---------------------------------------- | ---------------------- | ------------- | +| `7843444` | `78434445211333fd593578f67775331ce5ab037e` | 2026-07-31 17:57:23 | `chore: seed Cloud dogfood product brief` | Repo scaffolding / docs | Direct commit to `main` | +| `f41af8c` | `f41af8c65b4d1662527e5ad9fab8509e28b31808` | 2026-07-31 22:41:18 | `feat: ship H3 Prompt Studio` | Initial release | Ready [PR #8](https://github.com/cnjack/minimax-video-prompt-library/pull/8), squash-merged 2026-07-31T22:41:18Z | +| `389ce61` | `389ce6115c3418458e91eb63b6ba7a9d274d39f7` | 2026-07-31 23:50:19 | `feat: add H3 camera movement presets` | Feature + hardening | Ready [PR #11](https://github.com/cnjack/minimax-video-prompt-library/pull/11), squash-merged 2026-07-31T23:50:19Z | + +Author dates above are normalized to UTC from the commit's `+0800` timezone. +Report produced by the repository's release-steward process; delivery of the +branch and any pull request is owned by Cloud.