feat: add style kit production standards

This commit is contained in:
xz
2026-09-01 01:11:22 +08:00
parent 8caf947b80
commit a9c8eea271
13 changed files with 1391 additions and 13 deletions
+186 -9
View File
@@ -247,6 +247,8 @@ function seedRoles() {
["task:view", "查看项目协作任务"],
["task:manage", "创建、分派和管理项目协作任务"],
["task:complete", "更新本人负责的协作任务状态"],
["style:read", "查看组织、工作区和项目风格生产标准"],
["style:manage", "管理风格标准、品牌规范和项目绑定"],
["script:edit", "编辑剧本和对白"],
["script:read", "查看剧本、分集和镜头"],
["asset:edit", "编辑角色、场景和道具锁"],
@@ -283,17 +285,17 @@ function seedRoles() {
org_admin: [
"organization:manage", "organization:members:invite", "workspace:create", "workspace:manage",
"workspace:members:manage", "project:create", "project:manage", "project:members:manage",
"workflow:manage", "task:view", "task:manage", "task:complete", "model:manage", "model:approve", "usage:view", "billing:manage", "quota:manage", "qa:review", "delivery:approve", "delivery:view", "compliance:manage", "audit:view", "queue:manage", "voice:approve",
"workflow:manage", "task:view", "task:manage", "task:complete", "style:read", "style:manage", "model:manage", "model:approve", "usage:view", "billing:manage", "quota:manage", "qa:review", "delivery:approve", "delivery:view", "compliance:manage", "audit:view", "queue:manage", "voice:approve",
"system:settings:view", "service:health:view", "organization:roles:manage"
],
producer: ["project:create", "project:manage", "project:members:manage", "workflow:manage", "task:view", "task:manage", "task:complete", "script:read", "job:create", "job:prioritize", "usage:view", "delivery:approve", "delivery:view", "voice:approve"],
writer: ["script:read", "script:edit", "task:view", "task:complete", "job:create"],
art_director: ["asset:edit", "prompt:edit", "task:view", "task:complete", "job:create"],
voice_editor: ["voice:edit", "voice:approve", "task:view", "task:complete", "job:create"],
reviewer: ["script:read", "task:view", "task:complete", "qa:review", "voice:approve", "delivery:view"],
project_guest: ["script:read", "task:view", "delivery:view"],
project_editor: ["script:read", "script:edit", "asset:edit", "prompt:edit", "voice:edit", "task:view", "task:manage", "task:complete", "job:create", "delivery:view"],
project_viewer: ["script:read", "task:view", "delivery:view"]
producer: ["project:create", "project:manage", "project:members:manage", "workflow:manage", "task:view", "task:manage", "task:complete", "style:read", "style:manage", "script:read", "job:create", "job:prioritize", "usage:view", "delivery:approve", "delivery:view", "voice:approve"],
writer: ["script:read", "script:edit", "task:view", "task:complete", "style:read", "job:create"],
art_director: ["asset:edit", "prompt:edit", "task:view", "task:complete", "style:read", "style:manage", "job:create"],
voice_editor: ["voice:edit", "voice:approve", "task:view", "task:complete", "style:read", "job:create"],
reviewer: ["script:read", "task:view", "task:complete", "style:read", "qa:review", "voice:approve", "delivery:view"],
project_guest: ["script:read", "task:view", "style:read", "delivery:view"],
project_editor: ["script:read", "script:edit", "asset:edit", "prompt:edit", "voice:edit", "task:view", "task:manage", "task:complete", "style:read", "job:create", "delivery:view"],
project_viewer: ["script:read", "task:view", "style:read", "delivery:view"]
};
for (const [roleKey, permissionKeys] of Object.entries(rolePermissions)) {
for (const permissionKey of permissionKeys) {
@@ -362,6 +364,7 @@ function commercialEntitlementDefaults(billing = {}) {
["limit.workspaces", "工作区数量", "tenant", 8, "个", 1, "block", { commercialGate: "workspace:create" }],
["limit.projects", "项目数量", "production", 36, "个", 1, "block", { commercialGate: "project:create" }],
["limit.generation_jobs_monthly", "月度生成任务", "production", clipLimit, "job", 1, "block", { commercialGate: "generation_job:create" }],
["limit.style_kits", "风格生产标准", "production", 24, "套", 1, "block", { commercialGate: "style_kit:create" }],
["limit.storage_gb", "存储容量", "storage", storageGb, "GB", 1, "block", { commercialGate: "storage:write" }],
["limit.model_connectors", "模型连接器", "modelops", 16, "个", 1, "block", { commercialGate: "model_connector:create" }],
["limit.api_clients", "API 客户端", "system", 8, "个", 1, "block", { commercialGate: "api_client:create" }],
@@ -604,6 +607,179 @@ function seedModelRoutes() {
}
}
function seedStyleKits() {
const timestamp = now();
const kits = [
{
id: "stylekit-studio-guoman-vertical",
organizationId: "org-studio-lab",
workspaceId: "ws-local-aidrama",
projectId: null,
scopeMode: "workspace",
name: "星河国漫竖屏生产标准",
description: "工作区默认商用风格标准:原创国漫 2D、9:16、固定字幕与声线策略,所有关键帧强制单画面。",
status: "active",
visualProfile: {
styleFamily: "国产漫画 / 国漫 2D 动画",
linework: "干净线稿、清晰轮廓、轻赛璐璐阴影",
colorScript: "雷雨青绿、暖肤色、低饱和环境光",
cameraLanguage: "稳定中景、反应镜头、环境插入镜头优先",
continuityLocks: ["character", "costume", "location", "prop", "weather", "camera"]
},
subtitlePreset: {
language: "zh-CN",
fontFamily: "PingFang SC / Noto Sans SC",
position: "bottom-safe-area",
maxCharsPerLine: 18,
style: "白字深色描边,避免遮挡人物脸部和关键道具"
},
voicePolicy: {
finalVoiceMode: "fixed-reference-required",
forbidRandomNativeVoice: true,
ttsPreference: "local-or-owned-first",
fallbackMouthPlan: ["侧脸", "背影", "低头", "远景", "反应镜头", "环境插入镜头"]
},
deliverySpec: {
aspectRatio: "9:16",
resolution: "1080x1920",
fps: 24,
clipDurationSec: [5, 10],
exportFormat: "mp4",
projectFolder: "exports/{projectId}"
},
promptRules: {
positivePrefix: "ONE SINGLE COMPLETE 9:16 CHINESE ANIMATION FRAME, one continuous scene, one complete image.",
negativeTerms: ["split-screen", "comic panel", "collage", "contact sheet", "storyboard", "多格", "拼图", "分屏", "故事板拼图"],
renderNotes: ["角色服装、道具、天气和机位必须继承 continuity ledger", "每次图片生成 batch size 固定为 1"]
},
singleFramePolicy: {
enabled: true,
imageOutputCount: 1,
batchSize: 1,
forbiddenTerms: ["split-screen", "comic panel", "collage", "contact sheet", "storyboard", "多格", "拼图", "分屏", "多时间点"],
requiredPhrase: "one single complete frame"
},
namingRules: {
shotPattern: "{projectId}/S{season}E{episode}/shot-{shotNumber}-{assetKind}-{version}",
subtitlePattern: "{episodeId}-{voiceLineId}.srt",
deliveryPattern: "{projectName}-{episodeId}-{releaseVersion}"
},
qaPolicy: {
gates: ["single-frame", "continuity", "voice-rights", "subtitle-asr-alignment", "clip-transition"],
minimumReviewScore: 90,
requireLockedAssets: true
},
metadata: {
source: "seed://style-kits/studio-guoman-vertical",
commercialReference: "brand-kit-style-guide-production-standard"
},
bindProjectId: "thunder-mouth",
bindingNotes: "《雷雨口》商用 MVP 默认继承工作区国漫竖屏生产标准。"
},
{
id: "stylekit-northstar-fog-pilot",
organizationId: "org-northstar",
workspaceId: "ws-northstar-main",
projectId: "northstar-pilot",
scopeMode: "project",
name: "北辰雾境试播标准",
description: "北辰内容厂牌专用试播标准,用于验证跨组织隔离和项目级风格绑定。",
status: "active",
visualProfile: {
styleFamily: "原创国漫 2D 奇幻",
linework: "偏硬朗线条、雾中高反差边缘光",
colorScript: "冷雾灰、青铜色、少年角色暖色点光",
cameraLanguage: "稳定中景与环境压迫感,禁止多格构图",
continuityLocks: ["character", "location", "prop", "weather", "camera"]
},
subtitlePreset: {
language: "zh-CN",
fontFamily: "PingFang SC",
position: "bottom-safe-area",
maxCharsPerLine: 16,
style: "白字深描边"
},
voicePolicy: {
finalVoiceMode: "fixed-reference-required",
forbidRandomNativeVoice: true,
ttsPreference: "local-runner-only",
fallbackMouthPlan: ["远景", "侧脸", "反应镜头"]
},
deliverySpec: {
aspectRatio: "9:16",
resolution: "1080x1920",
fps: 24,
clipDurationSec: [5, 8],
exportFormat: "mp4",
projectFolder: "exports/{projectId}"
},
promptRules: {
positivePrefix: "ONE SINGLE COMPLETE 9:16 CHINESE ANIMATION FRAME, fantasy fog gate, one scene only.",
negativeTerms: ["split-screen", "comic panel", "collage", "contact sheet", "storyboard", "多格", "分屏"],
renderNotes: ["不得串用星河实验室角色或道具", "首尾帧必须来自当前项目"]
},
singleFramePolicy: {
enabled: true,
imageOutputCount: 1,
batchSize: 1,
forbiddenTerms: ["split-screen", "comic panel", "collage", "contact sheet", "storyboard", "多格", "拼图", "分屏"],
requiredPhrase: "one single complete frame"
},
namingRules: {
shotPattern: "{projectId}/pilot/shot-{shotNumber}-{version}",
subtitlePattern: "{projectId}-{voiceLineId}.srt",
deliveryPattern: "{projectName}-pilot-{releaseVersion}"
},
qaPolicy: {
gates: ["single-frame", "cross-org-isolation", "continuity", "clip-transition"],
minimumReviewScore: 92,
requireLockedAssets: true
},
metadata: {
source: "seed://style-kits/northstar-fog-pilot",
commercialReference: "tenant-isolated-production-standard"
},
bindProjectId: "northstar-pilot",
bindingNotes: "北辰试播项目强制使用项目级雾境风格标准。"
}
];
for (const kit of kits) {
insertIgnore(
`INSERT OR IGNORE INTO style_kits(
id, organization_id, workspace_id, project_id, scope_mode, name, description, status,
visual_profile_json, subtitle_preset_json, voice_policy_json, delivery_spec_json,
prompt_rules_json, single_frame_policy_json, naming_rules_json, qa_policy_json,
metadata_json, created_by, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'u-owner', ?, ?)`,
[
kit.id,
kit.organizationId,
kit.workspaceId,
kit.projectId,
kit.scopeMode,
kit.name,
kit.description,
kit.status,
JSON.stringify(kit.visualProfile),
JSON.stringify(kit.subtitlePreset),
JSON.stringify(kit.voicePolicy),
JSON.stringify(kit.deliverySpec),
JSON.stringify(kit.promptRules),
JSON.stringify(kit.singleFramePolicy),
JSON.stringify(kit.namingRules),
JSON.stringify(kit.qaPolicy),
JSON.stringify(kit.metadata),
timestamp,
timestamp
]
);
insertIgnore(
"INSERT OR IGNORE INTO project_style_kit_bindings(id, organization_id, workspace_id, project_id, style_kit_id, enforcement, notes, created_by, created_at, updated_at) VALUES (?, ?, ?, ?, ?, 'strict', ?, 'u-owner', ?, ?)",
[`binding-${kit.bindProjectId}-style-kit`, kit.organizationId, kit.workspaceId, kit.bindProjectId, kit.id, kit.bindingNotes, timestamp, timestamp]
);
}
}
function seedKnowledgeLibrary() {
const timestamp = now();
const content = [
@@ -1068,6 +1244,7 @@ withTransaction(() => {
seedModels();
seedModelCatalog();
seedModelRoutes();
seedStyleKits();
seedSystemGovernance();
seedWorkflowTemplates();
seedProductionGraph();