Files
agent/docs/superpowers/plans/2026-09-15-image-to-video-web.md

9.8 KiB
Raw Permalink Blame History

Image-to-video Web Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Integrate the real CMS-free image-to-video Skill with durable H3 tasks and a usable web interface. Architecture: Reuse attachment validation and approval broker; add a separate durable service and restricted MCP adapter. Keep image generation jobs independent of in-memory CMS/editor jobs and chat history. Tech Stack: Existing TypeScript/Pi/Fastify/React/Vitest; original Skill Python media validator; existing ffmpeg-static/ffprobe-static. Spec: docs/superpowers/specs/2026-09-15-image-to-video-web-design.md (approved by user).

Global Constraints

  • 不依赖 CMS 登录、剧名、字幕或旧剪辑器的参考/选段审核。
  • 首版只做单图新生成,不提供原片续接、批量生成、自动选图或生成封面功能。
  • 不自动调用 Seedance 或其他付费提供商;不宣称 H3 免费或已支持 10 秒。
  • 本地参考图外传和生成提交分别审批;不得自动审核素材、分配账户或发布广告。
  • 重启后已知 job_id 只查原任务;未知提交不得盲重投。不得伪造时长或审核 PASS。
  • 不发送密钥至模型/前端/日志。媒体端点必须防路径穿越、SSRF、重定向和错误内容。
  • 保留所有已有脏改动;仅提交本任务新增文件和本任务增量,不提交无关旧改动。

Task 1: Complete vertical slice (durable service, tools, routes and UI)

Files:

  • Create focused modules under packages/harness/src/image-video/: contracts, store/service, MCP adapter, media validation, tools. Tests under packages/harness/tests/image-video*.test.ts.
  • Modify packages/harness/src/tools/swads-mcp.ts only to expose reusable validated discovery/call plumbing if needed; preserve existing analytics allowlist. Export new modules through packages/harness/src/index.ts.
  • Modify apps/server/src/index.ts, apps/server/src/app.ts; create apps/server/src/routes/image-video.ts and tests apps/server/tests/image-video-api.test.ts.
  • Create apps/web/src/components/tools/ImageVideoPanel.tsx and tests apps/web/tests/image-video.test.tsx; integrate App.tsx, ApprovalDialog.tsx, ToolFallback.tsx and components.css as needed. Preserve current CMS UI but never require it for this flow.
  • Modify packages/harness/src/tools/tool-policy.ts, pi-event-adapter.ts for the new tools and safe public details.
  • Create docs/image-to-video-web.md with actual usage and explicit test/live limitations.

Interfaces / implementation guidance:

Use task IDs i2v_<uuid> and a versioned private JSON record with server-owned paths, ownerSessionId, stable request hash, reference hash, upload receipts, jobId, state, timestamps and revision. A local draft operation (i2v_create_task) resolves an attachment from the requesting Session and copies approved-local image bytes into the durable task directory; it must not upload. Subsequent tools i2v_upload_reference (ask), i2v_submit (ask), i2v_status (allow) consume only registered taskId, not arbitrary URL, tenant, file path or provider arguments. Preserve prompt/duration/image bindings from the draft through approval. Do not give a model a general mutation tool.

type ImageVideoDraft = { attachmentId: string; title: string; prompt: string; durationSeconds: number };
type ImageVideoPublicTask = {
  id: string; title: string; prompt: string; durationSeconds: number;
  state: string; createdAt: string; updatedAt: string;
  referenceUrl: string; videoUrl?: string; jobId?: string;
  error?: string; validation?: unknown;
};

Use private service methods create(sessionId, draft), upload(sessionId, taskId), submit(sessionId, taskId), refresh(taskId) and list()/view(taskId) with public redacted return DTOs. Tools must enforce owner Session. A same-origin, read-only local task history can display registered tasks across process restarts without granting a new Session permission to mutate them. No automatic cross-session reassignment. Keep already-submitted jobs collectible after restart, even when their old chat Session no longer exists. A timer or UI read-only refresh should resume job polling without involving the LLM. Query at most once per 30–60 seconds; serialize each task and coalesce concurrent requests.

Use /api/image-video/tasks for redacted local history and registered media read endpoints. Creation is a Session-scoped route and/or tool. Prefer a small dedicated image input + draft form that uses the existing attachment endpoint, then invokes this Skill through the composer with the exact draft/attachment identifiers; this allows references even without vision-enabled Qwen. Keep all transfer approvals explicit. If the model needs image inspection, explain current model image transmission separately; server thumbnail display is not model transmission.

Discover and validate required MCP tool schemas via listTools before submission; rely on actual structured response shapes, not guessed backend endpoints. Root controller will supply read-only live contract observations. Identity/platform ambiguity blocks upload. Persist every potentially mutating intent before calling remote tools. A timeout around submit must persist unknown_submission, never return to ready. A known returned job ID must be persisted even if user cancelled waiting; preserve in-flight result handling. Before a source upload retry, distinguish uninitiated, known upload receipt and unknown initialization/finalization; never duplicate an uncertain import blindly.

MP4 download uses only registered job artifact HTTPS URL, DNS/public-address checks and bounded bytes/time, no redirects. Validate full decode, video dimensions/frame rate/duration and audio using the original Skill scripts/media.py verify; exact-duration mismatch is failure, not ready. Store validation report and hash; preview remains not human reviewed. Bound process time and prohibit media tools from network access. Reuse existing safe media runtime helpers where suitable, without copying CMS download logic or fixed CMS hosts.

  • Step 1: RED — durable state tests. Test draft ownership, no external operations on create, separate approvals, duplicate concurrent submit, persisted job after reload, unknown submit blocks retry, unknown import blocks retry, stale task revisions, safe public DTO, independent CMS. Example behavioral assertion:
await expect(service.submit("ses_other", task.id)).rejects.toMatchObject({code:"I2V_TASK_NOT_FOUND"});
expect(remoteSubmissions).toHaveLength(0);

Run the focused harness tests and record real failing assertions before implementation. External provider/network calls may be faked, not service state or persistence.

  • Step 2: GREEN — implement minimal service and remote boundary. Atomic records, strict persisted schema, locked task operations, known-ID polling, safe URL/media validation. Validate recorded state by constructing a new service against the same temporary directory and proving no duplicate remote submit.
  • Step 3: RED/GREEN — API and tool access. Add tests of denied approval/no side effects, cross-session task binding, durable history after registry restart, same-origin JSON mutation requirements, registered-only media, HTTP 206/416 and no-store. Implement routes and tool policy, original Skill resource snapshot and production wiring. Deny unknown tool names.
  • Step 4: RED/GREEN — real UI behavior. Test image/draft input, exact approval parameters and thumbnail, unchecked decisions, loading/error/queue states, restored tasks, periodic status fetch with cleanup, registered-only video links and actual native player/download. Use jsdom only as component evidence, not end-to-end real generation proof.
  • Step 5: Verify and self-review. Run focused tests per iteration then full CI=true pnpm --config.verify-deps-before-run=false test, lint, typecheck and build. Review actual diff for credential reflection, arbitrary paths, duplicate requests and existing dirty edits. Write report with RED/GREEN evidence and all remaining live unknowns. Commit only isolated task changes; if modifying already-dirty files, use a task-specific delta commit or leave those files uncommitted and document why rather than absorbing unrelated edits.

Task 2: Independent review and live acceptance

Files: Review package/report in plan workspace; update docs/image-to-video-web.md with exact evidence. Root controller owns service start, browser and live acceptance, not the implementer.

  • Step 1: Independent review the new feature diff for spec compliance and code quality, especially restart/approval/unknown-submission semantics. Fix important findings with covering tests before live mutation.
  • Step 2: Run latest test/lint/typecheck/build; start local backend using existing hidden credential input without printing or saving keys. Read-only current MCP identity/schema checks must use the configured application token as well as connected-tool discovery.
  • Step 3: Browser test catalog discovery, new draft, reference preview, approval refusal and task history restoration with no CMS connection. Synthetic boundary tests must be visibly labelled as such.
  • Step 4: If there is a user-authorized reference image, submit one actual H3 task through page approvals. Otherwise stop at image selection; do not transmit earlier CMS images or manufacture approval of a new image. User's approval of this implementation is not approval of an unspecified remote submission.
  • Step 5: If a real job exists, poll it rather than resubmit, collect its exact MP4, run technical checks, watch/listen and verify actual webpage playback/download. If blocked on duration/provider/image approval, report that specifically; do not claim real generation completion.