Files
Kokorone/prisma/migrations/20260813083254_add_canon_research_pipeline/migration.sql
T
JefferyandClaude Sonnet 5 c66799ee7c feat: 完成 M 群組 — 既有作品考據與輕小說章節管線
共用場景資料庫(Scene/ScenePresence/SceneLine/SceneFact/SceneInteraction,
角色中立客觀記錄)與投影(ProjectionService 寫入 EpisodicMemory/
SemanticMemory/PersonalityTraitSnapshot/CharacterRelationshipEventLog,
逐一可追溯到來源場景)完全分層。歸屬信心分數(明示標記決定性、語言指紋
從已歸屬語料統計、場景名冊硬約束、對話輪替)與隔離區/指紋冷啟動(低信心
或樣本不足一律隔離,指紋精煉後可重新嘗試釋放)。多角色投影與修正(改一處
場景資料庫、reprojectScene 同步更新所有受影響角色,使用者互動記憶因為
從不帶 sourceSceneId 而結構性地不受影響,發現得晚的歸屬錯誤額外記一筆
CORRECTION 事件)。作品名冊建置門檻(達標自動建置,門檻檢查排在投影完成
之後才做,避免用到投影前的舊統計)。錨定點知識邊界(雙向:前進載入、
後退遺忘)與矛盾偵測(同優先序來源待人工確認,跨優先序可依小說原文>
官方設定集>動畫改編自動裁決)。插圖索引與衍生服裝目錄/姿勢語彙表。

刻意簡化:章節→場景切分與互動正負權重皆採結構化輸入(不做自動 NLP
場景邊界偵測與情感分析),比照 F-7 MockProvider 的做法——機制先做對,
之後有真實 NLP/LLM 能力再替換輸入來源。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 16:58:04 +08:00

194 lines
8.9 KiB
SQL

-- CreateTable
CREATE TABLE "illustrations" (
"id" TEXT NOT NULL PRIMARY KEY,
"workId" TEXT NOT NULL,
"volume" INTEGER NOT NULL,
"page" INTEGER,
"type" TEXT NOT NULL,
"sceneId" TEXT,
"description" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "illustrations_workId_fkey" FOREIGN KEY ("workId") REFERENCES "works" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "illustrations_sceneId_fkey" FOREIGN KEY ("sceneId") REFERENCES "scenes" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "costume_catalog_entries" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"illustrationId" TEXT,
"label" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "costume_catalog_entries_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "costume_catalog_entries_illustrationId_fkey" FOREIGN KEY ("illustrationId") REFERENCES "illustrations" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "pose_vocabulary_entries" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"illustrationId" TEXT,
"label" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "pose_vocabulary_entries_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "pose_vocabulary_entries_illustrationId_fkey" FOREIGN KEY ("illustrationId") REFERENCES "illustrations" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "scenes" (
"id" TEXT NOT NULL PRIMARY KEY,
"workId" TEXT NOT NULL,
"volume" INTEGER NOT NULL,
"chapterLabel" TEXT NOT NULL,
"storyOrder" INTEGER NOT NULL,
"summary" TEXT NOT NULL,
"rawText" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "scenes_workId_fkey" FOREIGN KEY ("workId") REFERENCES "works" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "scene_presences" (
"id" TEXT NOT NULL PRIMARY KEY,
"sceneId" TEXT NOT NULL,
"characterId" TEXT NOT NULL,
CONSTRAINT "scene_presences_sceneId_fkey" FOREIGN KEY ("sceneId") REFERENCES "scenes" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "scene_presences_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "scene_lines" (
"id" TEXT NOT NULL PRIMARY KEY,
"sceneId" TEXT NOT NULL,
"lineIndex" INTEGER NOT NULL,
"lineType" TEXT NOT NULL,
"rawText" TEXT NOT NULL,
"hasExplicitMarker" BOOLEAN NOT NULL DEFAULT false,
"markerCharacterId" TEXT,
"speakerCharacterId" TEXT,
"confidence" REAL NOT NULL DEFAULT 0,
"status" TEXT NOT NULL DEFAULT 'PENDING',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "scene_lines_sceneId_fkey" FOREIGN KEY ("sceneId") REFERENCES "scenes" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "scene_lines_speakerCharacterId_fkey" FOREIGN KEY ("speakerCharacterId") REFERENCES "characters" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "scene_facts" (
"id" TEXT NOT NULL PRIMARY KEY,
"sceneId" TEXT NOT NULL,
"eventLabel" TEXT NOT NULL,
"factKey" TEXT NOT NULL,
"factValue" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "scene_facts_sceneId_fkey" FOREIGN KEY ("sceneId") REFERENCES "scenes" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "scene_contradictions" (
"id" TEXT NOT NULL PRIMARY KEY,
"workId" TEXT NOT NULL,
"eventLabel" TEXT NOT NULL,
"factKey" TEXT NOT NULL,
"description" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'PENDING_HUMAN_REVIEW',
"resolution" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "scene_contradictions_workId_fkey" FOREIGN KEY ("workId") REFERENCES "works" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "language_corpus_entries" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"sceneId" TEXT,
"text" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "language_corpus_entries_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "personality_trait_snapshots" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"atStoryOrder" INTEGER NOT NULL,
"note" TEXT NOT NULL,
"expressivenessOverride" REAL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "personality_trait_snapshots_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "character_relationship_event_logs" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"otherCharacterId" TEXT NOT NULL,
"sceneId" TEXT,
"delta" REAL NOT NULL,
"description" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "character_relationship_event_logs_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "character_relationship_event_logs_otherCharacterId_fkey" FOREIGN KEY ("otherCharacterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "character_relationship_event_logs_sceneId_fkey" FOREIGN KEY ("sceneId") REFERENCES "scenes" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_episodic_memories" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"content" TEXT NOT NULL,
"occurredAt" DATETIME NOT NULL,
"emotionTag" TEXT NOT NULL,
"emotionIntensity" REAL NOT NULL,
"retrievalCount" INTEGER NOT NULL DEFAULT 0,
"lastRetrievedAt" DATETIME,
"source" TEXT NOT NULL,
"weight" REAL NOT NULL DEFAULT 1,
"relatedUserId" TEXT,
"isPrivate" BOOLEAN NOT NULL DEFAULT false,
"sourceSceneId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "episodic_memories_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "episodic_memories_relatedUserId_fkey" FOREIGN KEY ("relatedUserId") REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "episodic_memories_sourceSceneId_fkey" FOREIGN KEY ("sourceSceneId") REFERENCES "scenes" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_episodic_memories" ("characterId", "content", "createdAt", "emotionIntensity", "emotionTag", "id", "isPrivate", "lastRetrievedAt", "occurredAt", "relatedUserId", "retrievalCount", "source", "weight") SELECT "characterId", "content", "createdAt", "emotionIntensity", "emotionTag", "id", "isPrivate", "lastRetrievedAt", "occurredAt", "relatedUserId", "retrievalCount", "source", "weight" FROM "episodic_memories";
DROP TABLE "episodic_memories";
ALTER TABLE "new_episodic_memories" RENAME TO "episodic_memories";
CREATE TABLE "new_semantic_memories" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"fact" TEXT NOT NULL,
"about" TEXT NOT NULL,
"sourceSceneId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "semantic_memories_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "semantic_memories_sourceSceneId_fkey" FOREIGN KEY ("sourceSceneId") REFERENCES "scenes" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_semantic_memories" ("about", "characterId", "createdAt", "fact", "id") SELECT "about", "characterId", "createdAt", "fact", "id" FROM "semantic_memories";
DROP TABLE "semantic_memories";
ALTER TABLE "new_semantic_memories" RENAME TO "semantic_memories";
CREATE TABLE "new_works" (
"id" TEXT NOT NULL PRIMARY KEY,
"title" TEXT NOT NULL,
"volumeProgress" TEXT,
"worldview" TEXT,
"progressAnchor" TEXT,
"anchorStoryOrder" INTEGER NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_works" ("createdAt", "id", "progressAnchor", "title", "updatedAt", "volumeProgress", "worldview") SELECT "createdAt", "id", "progressAnchor", "title", "updatedAt", "volumeProgress", "worldview" FROM "works";
DROP TABLE "works";
ALTER TABLE "new_works" RENAME TO "works";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
-- CreateIndex
CREATE UNIQUE INDEX "scenes_workId_storyOrder_key" ON "scenes"("workId", "storyOrder");
-- CreateIndex
CREATE UNIQUE INDEX "scene_presences_sceneId_characterId_key" ON "scene_presences"("sceneId", "characterId");