refactor(frontend): consolidate workflow architecture and Playtest - #73
refactor(frontend): consolidate workflow architecture and Playtest#73xyh202131 wants to merge 52 commits into
Conversation
The MS2 frontend needs a reproducible workspace before any module code can land. Add the Vite entry, the pinned dependency manifest and lockfile, the three referenced TypeScript configs, and the ignore rules. The workspace installs and builds from a clean checkout.
Style and lint rules should be fixed before contributors start writing modules. Add the oxlint rule set and the oxfmt formatting profile for the frontend workspace. Formatting and lint results are identical on every machine and in CI.
The skeleton carries no test suite yet, but the test runner has to be wired for later work. Add the vitest config so it resolves the same path aliases as the application build. Tests can be added to any module without further setup.
Every upper layer needs a place for cross-module primitives that belong to no single domain. Add the shared layer with its pagination contract and a README stating what may live here. Modules have one agreed home for shared primitives instead of duplicating them.
The frontend has to state which business objects it owns and how each one is reached. Add one contract file per entity for character, project, task, generation, media, action template, playtest inspection and workflow run, plus the aggregate export. Upper layers depend on declared entity interfaces rather than on transport details.
The workflow steps the mentor reviewed need an explicit home separate from both entities and pages. Add contracts for character setup, generation, review, export and the workflow controller. Each use case has a named boundary that pages call instead of reaching into entities.
Routing targets have to exist before the application shell can wire them together. Add the home, projects, project detail, quick start, workflow editor, asset library, playtest and not found page modules. Every route in the product design maps to exactly one page module.
The page modules need a composition root that owns routing and layout. Add the app shell with its layout and route table, the browser entry point, and the base stylesheet. The application runs end to end and every page is reachable.
Reviewers need the branch checked automatically and a running preview to look at. Add the frontend workflow running lint, typecheck, test and build, and scope Vercel previews to frontend changes. Every pull request reports its own build status and preview URL.
The module boundaries and the interfaces expected from the backend must be reviewable without reading the code. Add the architecture document, the frontend README, and the API contract listing every endpoint the frontend calls. Backend and frontend can align on one written list of interfaces.
A run reopened after a refresh could not tell that a generation was still running, so the page had to either resubmit it or stall. Record the in-flight task id on WorkflowStep so it is saved with the run, and drop WorkflowTaskLink, which no structure ever held. Reopening a run recovers the pending task from its step instead of starting a second generation.
The vitest config sat outside every tsconfig include, so a type error in it would only surface when the runner started. Add it to the node project alongside the vite config. Both build-side configs are now covered by tsc -b.
A character is written when the user exports to the asset library, so it cannot hold work-in-progress state; the backend also returns no QC verdict and the product has no per-frame reject. Drop the action generation status, the frame qc and rejected fields, and the standalone playtest inspection entity; review now only reads frames. The asset tree describes confirmed assets only, and review results no longer need a second home.
Three structures carried assumptions a reader could not distinguish from settled decisions. State that multi-direction frame storage is undefined, that the MVP runs a single revision, and that an action id is unique only inside its outfit. Open questions are visible in the contracts instead of being rediscovered later.
The reduced module skeleton no longer includes playtest inspection or shared UI. Remove obsolete API and entity references and align the layout comment with app ownership. Documentation now matches the contracts and directories present in this branch.
The backend character contract has no standalone name field. Remove name from Character and CreateCharacterInput. The frontend now matches the confirmed character payload boundary.
The fixed workflow is not a backend resource. Remove WorkflowRunApis and update the public and controller contracts. Backend responsibilities now stop at generation and confirmed asset storage.
The API notes still described stale workflow and generation assumptions. Document frontend-owned workflow state, generation mapping, and assigned follow-ups. The architecture now reflects the latest backend reference and team decisions.
The backend scopes generation-task queries by both project and task identifiers. Add projectId to generation reads and task reads and subscriptions. Callers can now map directly to the documented task query endpoint.
Task lookup ownership is now confirmed against the backend API. Mark projectId plus taskId as resolved and remove the stale mismatch and question. Reviewers can see the current task query boundary without reopening the decision.
Workflow execution needs a stable boundary between generation records and backend tasks. Parse character-template results and bind generation IDs to task IDs. Require subscriptions to replay a current snapshot before later updates.
Workflow execution needs a frontend-owned snapshot that can survive page refreshes. Add the fixed step model, versioned local storage, and runtime hydration validation. Keep memory authoritative when persistence fails or stored data is invalid.
Quick Start and the editor need one frontend-owned progression boundary. Add character setup updates, generation submission, task recovery, and interruption handling. Advance valid results to candidate selection without exposing unfinished steps.
Workflow state and async recovery need regression coverage before page integration. Test persistence, submission deduplication, task replay, and interruption races. Verify the first generation slice through the real store and controller.
The skeleton documentation no longer reflects the implemented workflow slice. Record controller scope, recovery behavior, task replay, and local persistence limits. Keep editor, Quick Start automation, and later steps explicitly out of scope.
The workflow controller mixed process coordination, state transitions, and asynchronous task recovery in one file. Extract pure WorkflowRun transitions and the character-template task lifecycle behind the existing controller facade. Keep the public API and runtime behavior unchanged while making later workflow steps easier to add.
The new pure state boundary needs direct regression coverage alongside the existing controller tests. Cover fixed workflow creation, character setup normalization, and activation of the character-template step. Protect the extracted rules without changing production behavior.
The Character Setup feature exposed the asset creation DTO while the workflow controller expects step-local input. Change the submit callback to accept CharacterSetupStepInput. Allow Quick Start and Workflow Editor to connect without translating through an unrelated asset contract.
The Character Setup boundary previously drifted to an unrelated asset DTO. Add a type assertion for the submit callback parameter. Prevent the page-to-workflow contract from regressing.
- A/D keys now continue the currently selected action instead of forcing a switch to walk; mirror direction only set for walk actions - BFS flood fill uses pre-allocated Int32Array queue instead of dynamic array, eliminating GC pressure on large sprites - Largest component size tracked during BFS, removing Math.max+map - Fingerprint calculation merged into single pass over subject pixels instead of iterating all bounding box pixels first - Canvas element reused across frame reads via module-level singleton - Quality policy extracts hardcoded 256px thresholds into adaptive scale-aware policy derived from the sequence's own canvas baseline - README updated to reflect new A/D behavior
Quick Start needs to drive the frontend WorkflowRun without entering the editor. Add the page UI and an injectable service that prepares a project and delegates execution to WorkflowController. Unconfigured production wiring now fails explicitly instead of falling back to fake data.
Quick Start needs regression coverage across its page and controller boundary. Exercise the real WorkflowRun store and WorkflowController with only external ports substituted. Lock same-page execution, failure persistence, unexpected errors, and candidate delivery.
…, Generation, Media - http-client.ts: shared fetch wrapper with baseURL, JSON envelope parsing, and typed error handling - project.ts: ProjectApis adapter with snake_case↔camelCase mapping, perspective (1/2/3) and movement (1/2/3) enum conversion - character.ts: CharacterApis adapter mapping nested character_data outfits/actions/frames to flat frontend Character entity, with sensible defaults for backend-missing fields (rootMotion, kind, keyFrameIndex) - task.ts: TaskApis adapter with 2s polling fallback for subscribe() since backend has no WebSocket/SSE push - generation.ts: GenerationApis adapter routing character_template to POST /generation/image and first_frame/complete_animation to POST /generation/action - media.ts: MediaApis adapter for POST /media/upload with FormData - index.ts: unified re-export entry point All adapters conform to existing entity interfaces (ProjectApis, CharacterApis, GenerationApis, TaskApis) and are page-agnostic.
The article element for each node was missing an onClick binding, so clicking a node never called onNodeSelect — the inspector panel was permanently stuck on the initial master-gen node.
Align workflow editor with the asset-lab skeleton studio: - Add studio bar with brand, project info, mode selector, and actions - Add studio mode chooser (workflow vs natural creation) - Update node canvas to match asset-lab's paper-like design language - Add drag-to-connect from output ports (not just click) - Add armed link state for pending connections - Add node-canvas-hint bottom bar with contextual instructions - Add node-zoom controls with reset button - Add custom-action node type (06+ · CUSTOM) - Add description field to each node - Update node styling to match asset-lab's card design - Update connection visualization (solid for connected, dashed for suggested) - Update color palette to match asset-lab (--workspace-white, --ink, --muted, etc.) - Update inspection panel to match asset-lab's inspector design - Fix node click handler to properly update activeNode
The workflow editor was using custom CSS classes (studio-bar, node-canvas, node-card, etc.) but had no CSS file defining these styles, causing the page to render as unstyled content. - Add workflow-editor.css with styles ported from asset-lab/workflow-shell.css - Import CSS in index.tsx - Match asset-lab's paper-like design (--wf-white, --wf-ink, --wf-muted) - Style studio bar, node canvas, node cards, ports, hint bar, zoom controls - Style inspection panel with overline typography - Add responsive breakpoint for mobile (hide sidebar)
- Copy workflow-shell.css from asset-lab instead of custom CSS - Use exact class names: graph-node, graph-port, node-status, studio-bar, studio-mode-gateway, studio-mode-card, node-graph-workspace, etc. - Remove AI 智能生成 (natural creation) mode option - Match asset-lab's HTML structure for nodes, ports, and status indicators - Use asset-lab's overline typography and design tokens
…as-workspace CSS selector .production-canvas-workspace:has(> .studio-mode-gateway) requires studio-mode-gateway to be a direct child of production-canvas-workspace. Move it inside and add the footer note element.
There was a problem hiding this comment.
The current head has blocking build/test failures and several integration regressions; concrete findings are attached inline.
Validation: npm run format:check fails on 8 files; npm run typecheck and npm run build fail with TypeScript errors; npm test -- --maxWorkers=2 reports 2 failures (159 passing). npm run lint completes with 2 warnings.
| <Route path="/workflow-editor/:runId" element={<WorkflowEditorPage />} /> | ||
| <Route path="/workflow-editor/:runId/:stage" element={<WorkflowEditorPage />} /> | ||
| <Route path="/playtest/demo" element={<PlaytestDemoPage />} /> | ||
| <Route path="/playtest/:characterId/:outfitId" element={<PlaytestPage />} /> |
There was a problem hiding this comment.
[P1] Wire the production character adapter into this route. PlaytestPage treats an omitted apis prop as an error, so every visit to /playtest/:characterId/:outfitId currently renders “Playtest 角色接口尚未配置” and never loads the requested character. The newly added createCharacterApis() is not used anywhere else in the application.
| return { | ||
| id: String(raw.id), | ||
| projectId: String(raw.project_id), | ||
| type: raw.task_type as T, |
There was a problem hiding this comment.
[P1] Translate backend task types instead of only casting them. /generation/image returns task_type: "character_image", so this object exposes that runtime value even when typed as Generation<'character_template'>. character-template-task.ts then rejects it because generation.type !== 'character_template', causing every real character-template submission to fail immediately. Reuse the mapping already present in task.ts.
|
|
||
| const GENERATION_ENDPOINTS: Record<string, string> = { | ||
| character_template: '/generation/image', | ||
| first_frame: '/generation/action', |
There was a problem hiding this comment.
[P1] Route first_frame through the image-generation endpoint. The checked-in API contract explicitly maps first_frame to POST /generation/image with the confirmed character image as reference; sending this payload to /generation/action uses the wrong request schema and backend task type, so first-frame generation cannot work as documented.
|
|
||
| export class ApiError extends Error { | ||
| constructor( | ||
| public readonly status: number, |
There was a problem hiding this comment.
[P1] Avoid constructor parameter properties under this repository's TypeScript settings. tsconfig.app.json enables erasableSyntaxOnly, and these public readonly parameters trigger TS1294, which makes both npm run typecheck and npm run build fail. Declare the fields separately and assign them in the constructor.
| Outfit, | ||
| } from '@/entities' | ||
|
|
||
| import { del, get, patch, post } from './http-client' |
There was a problem hiding this comment.
[P1] Remove the unused del import. noUnusedLocals is enabled, so TS6133 here blocks npm run typecheck and npm run build on the current head.
| [], | ||
| ) | ||
|
|
||
| const handleWheel = useCallback((event: ReactWheelEvent) => { |
There was a problem hiding this comment.
[P1] Import/use React's wheel-event type and a JSX element type that is available with this TS configuration. ReactWheelEvent is undefined here and JSX.Element at line 126 has no namespace in scope, producing TS2552/TS2503 and preventing the frontend build.
|
|
||
| function getSharedContext(width: number, height: number): CanvasRenderingContext2D | null { | ||
| if (sharedCanvas === null) { | ||
| sharedCanvas = document.createElement('canvas') |
There was a problem hiding this comment.
[P2] Reset or recreate the shared canvas for each image before reading pixels. If one remote image taints this canvas, getImageData throws and the same-size canvas remains tainted for subsequent frames because width/height are not reassigned; later valid frames are then all reported as cross-origin failures. The module-level cached context also causes the two new image-geometry tests to reuse stale mocked contexts and fail.
Unify Quick Start and Workflow Editor around one controller, move transport and export behavior into stable entity and feature boundaries, and preserve complete animation results through review and publishing. Add real project and asset pages, recovery coverage, architecture guards, documentation, and repository-wide frontend formatting.\n\nCo-Authored-By: Codex <codex@openai.com>
Keep the integrated frontend pages and workflow controller while syncing the backend skeleton and CI from main. Remove the superseded action-template model and preserve the architecture boundary checks.
|
按提交者要求暂时关闭;未合入 main,保留分支供后续重新整理。 |
说明
本 PR 在现有 Playtest 与 WorkflowRun 基础上完成前端骨架整合,保留 Project、Character Assets、Creation Workflow、Generation Execution、Review and Publishing、Playtest and Delivery 六个业务模块,并接入仓库现有真实后端接口。
主要改动
WorkflowController和WorkflowRunStore。features/export-package。oxfmt统一格式化整个 frontend。验证
npm run format:checknpm run lintnpm run typechecknpm test:34 个测试文件、196 个测试通过npm run build