框架: A2收口——三域20表按主仓DDL原样建成(V1/V3/V5全文+V9V10V14V26V30触表ALTER摘录)+example_*四表(嵌入边表vector1024+HNSW);db skill交付(psycopg直连/卡片打印/文件事务);表映射与暂缓登记落档;README拍板台账①-④全拍+基座状态刷新

This commit is contained in:
zizi 2026-07-13 10:23:41 +08:00
parent 716bd3fbe4
commit ce1ab01b6d
10 changed files with 885 additions and 3 deletions

View File

@ -0,0 +1,38 @@
---
name: db
description: muse-example 实验库的唯一数据库通道——查询/DML/DDL/SQL 文件应用全走 scripts/db.pypsycopg 直连SELECT 结果卡片式打印即审查面。主会话与智能体要读写 PG 一律经此,不得裸连或散写一次性脚本。
---
# db —— muse-example 唯一数据库通道
对应 muse API 面:数据访问层。连接事实与凭据见 [`db/连接信息.md`](../../../db/连接信息.md)DSN 已锁死在脚本内,只连 `muse-example`)。
## 用法仓库根目录执行python 一律用 `.venv/bin/python`
```bash
# 查询:卡片式打印(默认最多 50 行、长值截 160 字)
.venv/bin/python .claude/skills/db/scripts/db.py query "SELECT id,title FROM muse_content_work"
.venv/bin/python .claude/skills/db/scripts/db.py query "SELECT ..." --json # JSON 数组输出(给脚本消费)
.venv/bin/python .claude/skills/db/scripts/db.py query "SELECT ..." --full # 长值不截断
.venv/bin/python .claude/skills/db/scripts/db.py query "SELECT ..." --max 200 # 放宽行数
# 单条写操作INSERT/UPDATE/DELETE/DDL报影响行数
.venv/bin/python .claude/skills/db/scripts/db.py exec "UPDATE ... WHERE ..."
# SQL 文件应用:整文件一个事务,失败全回滚
.venv/bin/python .claude/skills/db/scripts/db.py apply db/ddl/91-example实验私货.sql
# 表清单+活行数deleted=FALSE 计数,无 deleted 列的表计全行)
.venv/bin/python .claude/skills/db/scripts/db.py tables
```
## 红线
- **只连 `muse-example`**DSN 硬编码锁库;严禁改造脚本去碰共享 PG 上的 muse_local / muse_slice_live / *_test。
- 软删约定照主仓:删除=UPDATE `deleted=TRUE`不物理删example_* 表同样遵守)。
- 批量导入/嵌入等专用写路径由 import/embed skill 封装(内部同走 psycopg 直连),本 skill 承担通用查改与 DDL 应用。
- 建表/改表先落 `db/ddl/` 文件再 `apply`,不敲一次性 DDL——文件即审计。
## 元数据驱动
库内 `muse_meta_schema` / `muse_meta_field` / `muse_meta_visibility_policy` 是 23 型结构本体的权威行A3 起);拆书与抽取的字段合同一律 `query` 读库取,不再读 `meta/schemas/` YAMLYAML 退为设计稿与种子来源)。

View File

@ -0,0 +1,106 @@
#!/usr/bin/env python3
"""muse-example 唯一数据库通道db skill 脚本层)。
- DSN 锁死 muse-example严禁触碰共享 PG 上其他库muse_local / muse_slice_live / *_test
- query 卡片式打印=审查面exec 报影响行数apply 整文件一个事务失败全回滚
- 失败原样抛错不静默公约
"""
import json
import sys
import click
import psycopg
# 连接事实与凭据来源db/连接信息.md内网 Tailscale 段,凭据明文入仓为既定政策)
DSN = "postgresql://root:f6710e2d0294eb1c10e26a805a64bc54@100.64.0.8:5433/muse-example"
TRUNC = 160 # 卡片模式长值截断阈值(字符)
def _fmt(value, full: bool) -> str:
"""卡片值格式化NULL 显示 ∅;长值默认截断并标注总长。"""
if value is None:
return ""
s = str(value)
if not full and len(s) > TRUNC:
return s[:TRUNC] + f"…(共{len(s)}字)"
return s
@click.group()
def cli():
"""muse-example 数据库通道"""
@cli.command()
@click.argument("sql_text")
@click.option("--json", "as_json", is_flag=True, help="按 JSON 数组输出(给脚本消费)")
@click.option("--full", is_flag=True, help="长值不截断")
@click.option("--max", "max_rows", default=50, show_default=True, help="最多打印行数")
def query(sql_text: str, as_json: bool, full: bool, max_rows: int):
"""执行 SELECT卡片式打印审查面"""
with psycopg.connect(DSN) as conn:
cur = conn.execute(sql_text)
if cur.description is None:
raise click.ClickException("该语句无结果集——写操作请用 exec")
cols = [d.name for d in cur.description]
rows = cur.fetchall()
if as_json:
out = [dict(zip(cols, r)) for r in rows[:max_rows]]
click.echo(json.dumps(out, ensure_ascii=False, default=str, indent=1))
else:
width = max((len(c) for c in cols), default=0)
for i, r in enumerate(rows[:max_rows], 1):
click.echo(f"── 行 {i} " + "" * 30)
for c, v in zip(cols, r):
click.echo(f"{c:<{width}}{_fmt(v, full)}")
if len(rows) > max_rows:
click.echo(f"…(共 {len(rows)} 行,仅示 {max_rows} 行,--max 放宽)")
else:
click.echo(f"(共 {len(rows)} 行)")
@cli.command("exec")
@click.argument("sql_text")
def exec_(sql_text: str):
"""执行单条写操作INSERT/UPDATE/DELETE/DDL报影响行数。"""
with psycopg.connect(DSN) as conn:
cur = conn.execute(sql_text)
conn.commit()
n = cur.rowcount
click.echo(f"OK影响 {n} 行)" if n >= 0 else "OK")
@cli.command()
@click.argument("file", type=click.Path(exists=True))
def apply(file: str):
"""应用 SQL 文件:整文件一个事务(无参数走 simple protocol 支持多语句),失败全回滚。"""
with open(file, encoding="utf-8") as f:
sql = f.read()
with psycopg.connect(DSN) as conn:
conn.execute(sql)
conn.commit()
click.echo(f"已应用: {file}")
@cli.command()
def tables():
"""表清单 + 活行数(有 deleted 列的表计 deleted=FALSE其余计全行"""
with psycopg.connect(DSN) as conn:
names = [r[0] for r in conn.execute(
"SELECT tablename FROM pg_tables WHERE schemaname='public' ORDER BY tablename")]
for t in names:
has_deleted = conn.execute(
"SELECT 1 FROM information_schema.columns WHERE table_name=%s AND column_name='deleted'",
(t,)).fetchone()
where = " WHERE deleted = FALSE" if has_deleted else ""
n = conn.execute(f'SELECT count(*) FROM "{t}"{where}').fetchone()[0]
click.echo(f"{t:<45} {n}")
if __name__ == "__main__":
try:
cli()
except psycopg.Error as e:
# 数据库错误原样透出(可追踪、不静默)
click.echo(f"[db错误] {type(e).__name__}: {e}", err=True)
sys.exit(1)

View File

@ -52,7 +52,7 @@ agent-example/
| read-context | 统一读取器:读装配绑定→按用途+aiContext 三级裁剪→组装六分区上下文包→裁剪清单回显 | 统一创作数据读取器(专题-06 §7 | 现有文件版C4 升 PG 检索版(内部调 search | | read-context | 统一读取器:读装配绑定→按用途+aiContext 三级裁剪→组装六分区上下文包→裁剪清单回显 | 统一创作数据读取器(专题-06 §7 | 现有文件版C4 升 PG 检索版(内部调 search |
| confirm | 唯一确认通道:确认=commit、丢弃=restore仅创始人触发PG 版加知识行草稿→已确认翻转 | 双轨提交 / 候选三决策入口 | 现有 | | confirm | 唯一确认通道:确认=commit、丢弃=restore仅创始人触发PG 版加知识行草稿→已确认翻转 | 双轨提交 / 候选三决策入口 | 现有 |
| eval | 质量收敛环n=5、每轮只动一个变量、达标固化 `golden/` | 质量域 | 现有 | | eval | 质量收敛环n=5、每轮只动一个变量、达标固化 `golden/` | 质量域 | 现有 |
| db | `muse-example` 唯一数据库通道:ssh+容器 psql 封装(凭据按 `db/连接信息.md`),查询/DDL/DML 全走这,结果卡片式打印(=审查面) | 数据访问层 | A2 交付 | | db | `muse-example` 唯一数据库通道:psycopg 直连封装(凭据按 `db/连接信息.md`),查询/DDL/DML/SQL 文件应用全走这,结果卡片式打印(=审查面) | 数据访问层 | 已交付2026-07-13 |
| import | 导入解析txt→回目正则静态分章→作品/章行入库(调 db | 导入解析旅程 | B1 交付C8 用户旧稿复用 | | import | 导入解析txt→回目正则静态分章→作品/章行入库(调 db | 导入解析旅程 | B1 交付C8 用户旧稿复用 |
| embed | New-API 嵌入封装Qwen3-Embedding-8B、`dimensions:1024``--noproxy`、批量+失败重试 | AI 网关(嵌入) | B2 交付 | | embed | New-API 嵌入封装Qwen3-Embedding-8B、`dimensions:1024``--noproxy`、批量+失败重试 | AI 网关(嵌入) | B2 交付 |
| search | 向量检索意图→embed→pgvector 相似度召回→授权过滤(仅已确认+已绑定)+字段裁剪→带相似度分的结果集 | 知识检索 | B3 交付 | | search | 向量检索意图→embed→pgvector 相似度召回→授权过滤(仅已确认+已绑定)+字段裁剪→带相似度分的结果集 | 知识检索 | B3 交付 |
@ -218,8 +218,8 @@ flowchart LR
## 九、当前位置2026-07-10 快照) ## 九、当前位置2026-07-10 快照)
- 执行主线=§七闭环序知识域A/B先行创作域C后置待 B5 过门后按 C 线走。 - 执行主线=§七闭环序知识域A/B先行创作域C后置待 B5 过门后按 C 线走。
- **拍板台账**:①已拍 A——B2 首轮公共面只拆 5 型范式,双层型二轮凭脚手架实据定;细纲字数比例已拍入 outline schema。**待拍**:②参考书书单——封神演义因创始人未读降级为分章正则测试样本,换创始人熟读的 23 本(已定框架=每本全本导入分章+首轮拆 3050 章原文只入私有库公共面只有脱敏范式③A2 口径(主仓表原样不改列+私货全进 `example_*`);④整序确认。齐后从 A1 起跑 - **拍板台账(①–④已全拍)**①B2 首轮公共面只拆 5 型范式,双层型二轮凭脚手架实据定;细纲字数比例已拍入 outline schema。②已拍2026-07-10——参考书=`../小说清单/` 7 本**全部导入**私有库;首轮拆书 4 本:超神机械师/机战无限/深空之影/机动风暴(每本 3050 章;原文只入私有库,公共面只有脱敏范式)。③已拍——主仓表原样不改列+私货全进 `example_*`。④已拍——整序确认A1 已起跑B2 跑批前有成本确认闸)
- **能力就位**skill 16 只(基建 7read-context/confirm/eval 现有+db/import/embed/search 按 A2B3 交付;功能 9 全建成,对齐官方规范)× agent 5已瘦身为身份段prompt 三段式(身份段×功能 skill×L0上下文=四层+章级基线包共享前缀+按 agent 差异矩阵read-context skill 为准);拆书=workflow 编排+逐章 agent 有界任务parse-book skill 为准)。 - **能力就位**skill 16 只(基建 7read-context/confirm/eval 现有+db/import/embed/search 按 A2B3 交付;功能 9 全建成,对齐官方规范)× agent 5已瘦身为身份段prompt 三段式(身份段×功能 skill×L0上下文=四层+章级基线包共享前缀+按 agent 差异矩阵read-context skill 为准);拆书=workflow 编排+逐章 agent 有界任务parse-book skill 为准)。
- **基座**本机 psycopg 直连与 psql 18.4 均验通;`muse-example` 库与 vector 插件**尚未创建**A1 第一步);凭据与配方在 `db/连接信息.md``.venv` 已建requirements.txt - **基座**A1/A2 已收口2026-07-13——`muse-example` 库+pgvector 0.8.5 验通容器重建恢复命令见连接信息24 表建成(主仓一致 20 + `example_*` 4映射与暂缓登记见 `db/表映射.md`db skill 已交付;凭据与配方在 `db/连接信息.md``.venv` 丢失时按 requirements.txt 重建即用
- **待审资产已清零2026-07-10 创始人清理)**:文件版首轮的 13 张范式卡、参考书档案 extracted 态、《焚忆》全部文件资产已清除,工作区(干净 clone无任何待审存量首轮拆书的字段设计发现已蒸馏入 `meta/schemas/`(已提交),不受影响。 - **待审资产已清零2026-07-10 创始人清理)**:文件版首轮的 13 张范式卡、参考书档案 extracted 态、《焚忆》全部文件资产已清除,工作区(干净 clone无任何待审存量首轮拆书的字段设计发现已蒸馏入 `meta/schemas/`(已提交),不受影响。
- 进度惯例:看 git log 与本节拍板台账,不设过程状态文档。 - 进度惯例:看 git log 与本节拍板台账,不设过程状态文档。

View File

@ -0,0 +1,39 @@
-- 主仓 ALTER 摘录(只取触达 V1/V3/V5 三个 init 文件所建 20 表的语句,一字不改)
-- 口径(创始人拍板③ 2026-07-10主仓表原样不改列本文件各段出处逐一注明。
-- 未摘录说明V9/V10/V14 等文件中"新建表"部分planning_section、meta 治理 8 表、
-- knowledge RAGFlow 14 表、各 outbox 表)实验现阶段不用,暂缓建表,登记见 db/表映射.md。
-- ── 出自 sql/muse/V9__extend_content_real_api_schema.sql ──
ALTER TABLE muse_content_export_task
ADD COLUMN IF NOT EXISTS download_expires_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS completed_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS progress INT NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS source_snapshot JSONB;
-- ── 出自 sql/muse/V10__extend_meta_real_api_schema.sql ──
CREATE UNIQUE INDEX uk_muse_meta_schema_version_active_schema_id
ON muse_meta_schema_version(tenant_id, schema_id)
WHERE active_flag = TRUE AND deleted = FALSE;
ALTER TABLE muse_meta_protection_node
ADD COLUMN IF NOT EXISTS node_type VARCHAR(64) NOT NULL DEFAULT 'system',
ADD COLUMN IF NOT EXISTS irreplaceable_reason TEXT,
ADD COLUMN IF NOT EXISTS permission_requirement JSONB,
ADD COLUMN IF NOT EXISTS audit_requirement JSONB,
ADD COLUMN IF NOT EXISTS shadow_to_canonical_boundary JSONB,
ADD COLUMN IF NOT EXISTS observability_metrics JSONB;
-- ── 出自 sql/muse/V14__extend_knowledge_ragflow_real_api_schema.sql ──
ALTER TABLE muse_knowledge_draft
ALTER COLUMN source_snapshot_id TYPE VARCHAR(128) USING source_snapshot_id::text;
ALTER TABLE muse_knowledge_draft
ALTER COLUMN authorization_snapshot_id TYPE VARCHAR(128) USING authorization_snapshot_id::text;
ALTER TABLE muse_knowledge_binding
ALTER COLUMN source_snapshot_id TYPE VARCHAR(128) USING source_snapshot_id::text;
ALTER TABLE muse_knowledge_binding
ALTER COLUMN authorization_snapshot_id TYPE VARCHAR(128) USING authorization_snapshot_id::text;
-- ── 出自 sql/muse/V30__widen_authorization_snapshot_id_to_varchar.sql ──
-- (同文件另有 muse_ai_suggestion 一条,该表实验未建,不摘)
ALTER TABLE muse_content_block_source_attribution
ALTER COLUMN authorization_snapshot_id TYPE VARCHAR(128) USING authorization_snapshot_id::text;

View File

@ -0,0 +1,96 @@
-- 实验私货表(口径③:主仓表原样不改列,实验扩展全进 example_* 前缀)
-- 公共列/触发器沿用主仓惯例creator/create_time/updater/update_time/deleted/tenant_id + updated_at 触发器);
-- tenant_id/creator 按拍板默认系统主账号=1写入层给值列默认仍照主仓惯例
-- 软引用无外键(同主仓约定:引用完整性由应用/skill 层保证)。
-- ══ example_reference_work参考书档案23 型之 reference_work 的库内实例载体)══
-- 一本参考书 = muse_content_work 一行(原文私有库) + 本表一行(档案与拆书进度)。
CREATE TABLE example_reference_work (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL, -- → muse_content_work.id软引用
author VARCHAR(100), -- 作者
source_file VARCHAR(500), -- 原始 txt 文件名
declared_chapter_count INT, -- 原文件头部声明章数(无则 NULL
imported_chapter_count INT NOT NULL DEFAULT 0, -- 实际导入章数
char_count BIGINT NOT NULL DEFAULT 0, -- 全文字符数
parse_scope JSONB, -- 首轮拆书范围,如 {"from":1,"to":50}
parse_status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending/parsing/parsed
notes TEXT, -- 清洗记录/章题格式特点等备注
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_example_reference_work UNIQUE (tenant_id, work_id)
);
CREATE TRIGGER trg_example_reference_work_updated_at BEFORE UPDATE ON example_reference_work FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ══ example_parse_task拆书任务状态机workflow 断点续跑与幂等,状态全在库)══
-- 一章一行两阶段各自状态scaffold=细纲逆推+实体脚手架pattern=范式拆解。
CREATE TABLE example_parse_task (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL, -- → muse_content_work.id
chapter_id BIGINT NOT NULL, -- → muse_content_chapter.id
scaffold_status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending/running/done/failed
pattern_status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending/running/done/failed
attempt_count INT NOT NULL DEFAULT 0, -- 累计尝试次数(含重试)
agent_model VARCHAR(50), -- 执行模型标记(审计用)
error_message TEXT, -- 最近一次失败原因
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_example_parse_task UNIQUE (tenant_id, work_id, chapter_id),
CONSTRAINT chk_example_parse_task_scaffold CHECK (scaffold_status IN ('pending','running','done','failed')),
CONSTRAINT chk_example_parse_task_pattern CHECK (pattern_status IN ('pending','running','done','failed'))
);
CREATE INDEX idx_example_parse_task_work ON example_parse_task(tenant_id, work_id, scaffold_status, pattern_status);
CREATE TRIGGER trg_example_parse_task_updated_at BEFORE UPDATE ON example_parse_task FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ══ example_parse_scaffold逐章脚手架parse-book 2b 第一步产物)══
-- 细纲字数比例按 outline schema 拍板值(章细纲=原文 35%);实体清单供判重与二轮双层型决策。
CREATE TABLE example_parse_scaffold (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL, -- → muse_content_work.id
chapter_id BIGINT NOT NULL, -- → muse_content_chapter.id
outline_text TEXT, -- 逆推细纲(对原文 35% 字数)
entities JSONB, -- 实体清单 [{type,name,brief}]
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_example_parse_scaffold UNIQUE (tenant_id, chapter_id)
);
CREATE INDEX idx_example_parse_scaffold_work ON example_parse_scaffold(tenant_id, work_id);
CREATE TRIGGER trg_example_parse_scaffold_updated_at BEFORE UPDATE ON example_parse_scaffold FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ══ example_knowledge_embedding知识行嵌入边表vector(1024)Qwen3-Embedding-8B══
-- 挂 draft草稿期或 entity确认后至少其一非空content_hash 幂等判重(同文同模型不重嵌)。
CREATE TABLE example_knowledge_embedding (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
draft_id BIGINT, -- → muse_knowledge_draft.id软引用
entity_id BIGINT, -- → muse_knowledge_entity.id软引用
content_hash CHAR(64) NOT NULL, -- 嵌入文本 sha256幂等键
embed_text TEXT NOT NULL, -- 被嵌入文本(名称+摘要+正文拼接)
model VARCHAR(100) NOT NULL DEFAULT 'Qwen/Qwen3-Embedding-8B',
dimensions INT NOT NULL DEFAULT 1024,
embedding vector(1024) NOT NULL,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_example_knowledge_embedding UNIQUE (tenant_id, content_hash, model),
CONSTRAINT chk_example_knowledge_embedding_ref CHECK (draft_id IS NOT NULL OR entity_id IS NOT NULL)
);
CREATE INDEX idx_example_knowledge_embedding_draft ON example_knowledge_embedding(tenant_id, draft_id) WHERE draft_id IS NOT NULL;
CREATE INDEX idx_example_knowledge_embedding_entity ON example_knowledge_embedding(tenant_id, entity_id) WHERE entity_id IS NOT NULL;
-- 余弦相似度检索索引B3 search skill 用 <=> 召回数据量小HNSW 默认参数即可)
CREATE INDEX idx_example_knowledge_embedding_hnsw ON example_knowledge_embedding USING hnsw (embedding vector_cosine_ops);
CREATE TRIGGER trg_example_knowledge_embedding_updated_at BEFORE UPDATE ON example_knowledge_embedding FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

View File

@ -0,0 +1,180 @@
-- Muse Content 模块初始 SchemaPostgreSQL 16
-- 影响范围作品、章节、Block、来源归因、导入导出任务。
-- 说明:业务表不使用数据库外键,引用完整性由应用层在权限、租户和 owner 校验后保证。
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.update_time = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE muse_content_work (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
owner_user_id BIGINT NOT NULL,
title VARCHAR(200) NOT NULL,
description TEXT,
genre VARCHAR(50),
cover_image_url TEXT,
summary TEXT,
status VARCHAR(20) NOT NULL DEFAULT 'writing',
work_schema_id BIGINT,
import_status VARCHAR(20),
parse_status VARCHAR(20),
word_count INT NOT NULL DEFAULT 0,
chapter_count INT NOT NULL DEFAULT 0,
command_id VARCHAR(120),
revision INT NOT NULL DEFAULT 1,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_muse_content_work_owner ON muse_content_work(tenant_id, owner_user_id, update_time);
CREATE INDEX idx_muse_content_work_status ON muse_content_work(tenant_id, status);
CREATE UNIQUE INDEX uk_muse_content_work_command ON muse_content_work(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_content_work_updated_at BEFORE UPDATE ON muse_content_work FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_content_chapter (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
title VARCHAR(200) NOT NULL,
order_no INT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'draft',
goal_snapshot JSONB,
outline_snapshot JSONB,
parse_review_status VARCHAR(20),
command_id VARCHAR(120),
revision INT NOT NULL DEFAULT 1,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_content_chapter_work_order UNIQUE (tenant_id, work_id, order_no)
);
CREATE INDEX idx_muse_content_chapter_work ON muse_content_chapter(tenant_id, work_id);
CREATE UNIQUE INDEX uk_muse_content_chapter_command ON muse_content_chapter(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_content_chapter_updated_at BEFORE UPDATE ON muse_content_chapter FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_content_block (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
chapter_id BIGINT NOT NULL,
order_no INT NOT NULL,
block_type VARCHAR(30) NOT NULL DEFAULT 'scene',
title VARCHAR(500),
content_doc JSONB,
content_text TEXT,
revision INT NOT NULL DEFAULT 1,
word_count INT NOT NULL DEFAULT 0,
command_id VARCHAR(120),
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_content_block_chapter_order UNIQUE (tenant_id, chapter_id, order_no)
);
CREATE INDEX idx_muse_content_block_work ON muse_content_block(tenant_id, work_id);
CREATE INDEX idx_muse_content_block_chapter ON muse_content_block(tenant_id, chapter_id);
CREATE UNIQUE INDEX uk_muse_content_block_command ON muse_content_block(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_content_block_updated_at BEFORE UPDATE ON muse_content_block FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_content_block_source_attribution (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
block_id BIGINT NOT NULL,
revision INT NOT NULL,
source_type VARCHAR(50) NOT NULL,
source_object_id VARCHAR(100),
source_version INT,
lineage_payload JSONB,
authorization_snapshot_id BIGINT,
source_status VARCHAR(30),
license_restriction_snapshot JSONB,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_content_block_src_revision UNIQUE (tenant_id, block_id, revision)
);
CREATE INDEX idx_muse_content_block_src_block ON muse_content_block_source_attribution(tenant_id, block_id);
CREATE TRIGGER trg_muse_content_block_src_updated_at BEFORE UPDATE ON muse_content_block_source_attribution FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_content_import_task (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
owner_user_id BIGINT NOT NULL,
source_type VARCHAR(50) NOT NULL,
source_snapshot JSONB,
status VARCHAR(30) NOT NULL DEFAULT 'queued',
error_code VARCHAR(80),
error_message TEXT,
command_id VARCHAR(120) NOT NULL,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_content_import_command UNIQUE (tenant_id, command_id)
);
CREATE INDEX idx_muse_content_import_work ON muse_content_import_task(tenant_id, work_id, status);
CREATE TRIGGER trg_muse_content_import_updated_at BEFORE UPDATE ON muse_content_import_task FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_content_export_task (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
owner_user_id BIGINT NOT NULL,
export_format VARCHAR(30) NOT NULL,
status VARCHAR(30) NOT NULL DEFAULT 'queued',
credential_id VARCHAR(120),
package_ref TEXT,
error_code VARCHAR(80),
error_message TEXT,
command_id VARCHAR(120) NOT NULL,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_content_export_command UNIQUE (tenant_id, command_id)
);
CREATE INDEX idx_muse_content_export_work ON muse_content_export_task(tenant_id, work_id, status);
CREATE TRIGGER trg_muse_content_export_updated_at BEFORE UPDATE ON muse_content_export_task FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_content_command_log (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
command_id VARCHAR(120) NOT NULL,
command_type VARCHAR(80) NOT NULL,
owner_user_id BIGINT NOT NULL,
target_type VARCHAR(50),
target_id BIGINT,
request_hash VARCHAR(128),
result_snapshot JSONB,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_content_command UNIQUE (tenant_id, command_id)
);
CREATE INDEX idx_muse_content_command_owner ON muse_content_command_log(tenant_id, owner_user_id, create_time);
CREATE TRIGGER trg_muse_content_command_updated_at BEFORE UPDATE ON muse_content_command_log FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

View File

@ -0,0 +1,28 @@
-- 修复 content 章节/Block 软删后 order_no 唯一约束碰撞 schema bug。
--
-- 背景:muse_content_chapter / muse_content_block 继承 yudao 软删(deleted 列 + @TableLogic,
-- 删除是 UPDATE deleted=1、行仍在表)。但 uk_muse_content_chapter_work_order(tenant_id, work_id, order_no)
-- 与 uk_muse_content_block_chapter_order(tenant_id, chapter_id, order_no) 是完整唯一约束、不含 deleted 条件,
-- 软删行仍占 order_no 名额;而 createChapter/createBlock 用 orderNo = selectCount(active)+1(只算未删行),
-- 删章节/Block 后再建同序号 → 与软删行碰撞 → PostgreSQL duplicate key → 500 系统异常。
-- (反假绿:studio 前端补齐 chapter create 契约字段后真后端建章才暴露此 bug;见 docs/mvp/进度总账.md。)
--
-- 修法:改为 partial unique index(WHERE deleted = FALSE),软删行不占名额、active 行唯一性不变,
-- 对齐同库 uk_muse_content_chapter_command 等既有 partial index 惯例。
-- 安全性:order_no uk 不被任何 ON CONFLICT 引用(content 的 ON CONFLICT 仅在 command/outbox 表、用完整 uk),
-- 故改 partial 不影响 insert/ON CONFLICT 仲裁(区别于 V22 须保留完整索引的 command_id 场景)。
-- 幂等:DROP CONSTRAINT/INDEX IF EXISTS 后重建,对已应用 V1 的库与全新库均安全。
-- 章节:DROP 原完整唯一约束,改建 partial unique index(同名)
ALTER TABLE muse_content_chapter DROP CONSTRAINT IF EXISTS uk_muse_content_chapter_work_order;
DROP INDEX IF EXISTS uk_muse_content_chapter_work_order;
CREATE UNIQUE INDEX uk_muse_content_chapter_work_order
ON muse_content_chapter (tenant_id, work_id, order_no)
WHERE deleted = FALSE;
-- Block:同理(createBlock 同样用 selectCountByChapterId(active)+1,删后重建同序号会碰撞)
ALTER TABLE muse_content_block DROP CONSTRAINT IF EXISTS uk_muse_content_block_chapter_order;
DROP INDEX IF EXISTS uk_muse_content_block_chapter_order;
CREATE UNIQUE INDEX uk_muse_content_block_chapter_order
ON muse_content_block (tenant_id, chapter_id, order_no)
WHERE deleted = FALSE;

View File

@ -0,0 +1,133 @@
-- Muse Meta 模块初始 SchemaPostgreSQL 16
-- 影响范围MetaSchema、字段、可见性策略、保护节点、功能链路。
CREATE TABLE muse_meta_schema (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
schema_key VARCHAR(100) NOT NULL,
domain VARCHAR(20) NOT NULL,
scope VARCHAR(20) NOT NULL,
target_type VARCHAR(50),
display_name VARCHAR(200) NOT NULL,
active_version_id BIGINT,
effective_scope JSONB,
projection_version INT NOT NULL DEFAULT 1,
status VARCHAR(20) NOT NULL DEFAULT 'active',
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_meta_schema_key UNIQUE (tenant_id, domain, scope, target_type, schema_key)
);
CREATE TRIGGER trg_muse_meta_schema_updated_at BEFORE UPDATE ON muse_meta_schema FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_meta_schema_version (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
schema_id BIGINT NOT NULL,
schema_key VARCHAR(100) NOT NULL,
version_no INT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'draft',
active_flag BOOLEAN NOT NULL DEFAULT FALSE,
effective_scope JSONB,
field_contract_snapshot JSONB,
impact_preview_snapshot JSONB,
rollback_from_version_id BIGINT,
rollback_to_version_id BIGINT,
published_by VARCHAR(64),
published_at TIMESTAMP,
activated_by VARCHAR(64),
activated_at TIMESTAMP,
change_note VARCHAR(500),
command_id VARCHAR(120),
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_meta_schema_version_key UNIQUE (tenant_id, schema_key, version_no)
);
CREATE INDEX idx_muse_meta_schema_ver_sid ON muse_meta_schema_version(tenant_id, schema_id);
CREATE UNIQUE INDEX uk_muse_meta_schema_ver_command ON muse_meta_schema_version(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_meta_schema_version_updated_at BEFORE UPDATE ON muse_meta_schema_version FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_meta_field (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
schema_version_id BIGINT NOT NULL,
field_key VARCHAR(100) NOT NULL,
display_name VARCHAR(200) NOT NULL,
field_type VARCHAR(20) NOT NULL,
is_required BOOLEAN NOT NULL DEFAULT FALSE,
default_value JSONB,
enum_values JSONB,
validation_rules JSONB,
sort_order INT NOT NULL DEFAULT 0,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_muse_meta_field_ver ON muse_meta_field(tenant_id, schema_version_id);
CREATE TRIGGER trg_muse_meta_field_updated_at BEFORE UPDATE ON muse_meta_field FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_meta_visibility_policy (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
schema_version_id BIGINT NOT NULL,
ui_visible BOOLEAN NOT NULL DEFAULT TRUE,
ai_context BOOLEAN NOT NULL DEFAULT FALSE,
user_editable BOOLEAN NOT NULL DEFAULT TRUE,
user_searchable BOOLEAN NOT NULL DEFAULT FALSE,
exportable BOOLEAN NOT NULL DEFAULT FALSE,
policy_snapshot JSONB,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_muse_meta_vis_policy_ver ON muse_meta_visibility_policy(tenant_id, schema_version_id);
CREATE TRIGGER trg_muse_meta_vis_policy_updated_at BEFORE UPDATE ON muse_meta_visibility_policy FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_meta_protection_node (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
node_key VARCHAR(100) NOT NULL,
display_name VARCHAR(200) NOT NULL,
owner_module VARCHAR(50) NOT NULL,
replaceable BOOLEAN NOT NULL DEFAULT FALSE,
policy_snapshot JSONB,
status VARCHAR(20) NOT NULL DEFAULT 'active',
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_meta_protection_node UNIQUE (tenant_id, node_key)
);
CREATE TRIGGER trg_muse_meta_protection_node_updated_at BEFORE UPDATE ON muse_meta_protection_node FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_meta_function_chain (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
chain_key VARCHAR(100) NOT NULL,
active_version VARCHAR(50),
chain_snapshot JSONB,
status VARCHAR(20) NOT NULL DEFAULT 'active',
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_meta_function_chain UNIQUE (tenant_id, chain_key)
);
CREATE TRIGGER trg_muse_meta_function_chain_updated_at BEFORE UPDATE ON muse_meta_function_chain FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

View File

@ -0,0 +1,206 @@
-- Muse Knowledge 模块初始 SchemaPostgreSQL 16
-- 影响范围:用户/全局知识库、资料版本、实体关系、草稿、作品绑定。
CREATE TABLE muse_knowledge_base (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description VARCHAR(500),
kb_type VARCHAR(20) NOT NULL DEFAULT 'user',
owner_user_id BIGINT,
source_market_asset_id BIGINT,
status VARCHAR(20) NOT NULL DEFAULT 'active',
active_version INT NOT NULL DEFAULT 1,
visibility_policy JSONB,
license_snapshot_id BIGINT,
command_id VARCHAR(120),
revision INT NOT NULL DEFAULT 1,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_muse_kb_owner_status ON muse_knowledge_base(tenant_id, owner_user_id, status);
CREATE INDEX idx_muse_kb_type ON muse_knowledge_base(tenant_id, kb_type);
CREATE UNIQUE INDEX uk_muse_kb_command ON muse_knowledge_base(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_knowledge_base_updated_at BEFORE UPDATE ON muse_knowledge_base FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_knowledge_document (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
kb_id BIGINT NOT NULL,
title VARCHAR(200) NOT NULL,
file_name VARCHAR(500),
file_size BIGINT,
mime_type VARCHAR(100),
file_hash VARCHAR(100),
storage_ref VARCHAR(500),
scan_status VARCHAR(20) NOT NULL DEFAULT 'pending',
parse_status VARCHAR(20),
index_status VARCHAR(20),
retention_policy JSONB,
author VARCHAR(200),
source_url VARCHAR(1000),
tags JSONB,
command_id VARCHAR(120),
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_muse_kb_doc_kb ON muse_knowledge_document(tenant_id, kb_id, scan_status);
CREATE INDEX idx_muse_kb_doc_hash ON muse_knowledge_document(tenant_id, file_hash);
CREATE UNIQUE INDEX uk_muse_kb_doc_command ON muse_knowledge_document(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_knowledge_document_updated_at BEFORE UPDATE ON muse_knowledge_document FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_knowledge_document_version (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
document_id BIGINT NOT NULL,
version INT NOT NULL,
file_hash VARCHAR(100) NOT NULL,
storage_ref VARCHAR(500),
content_hash VARCHAR(100),
source_snapshot_id BIGINT,
scan_status VARCHAR(20) NOT NULL DEFAULT 'pending',
parse_status VARCHAR(20) NOT NULL DEFAULT 'pending',
processing_status VARCHAR(20) NOT NULL DEFAULT 'pending',
previous_version_id BIGINT,
change_summary JSONB,
change_reason VARCHAR(500),
command_id VARCHAR(120),
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_kb_doc_ver UNIQUE (tenant_id, document_id, version)
);
CREATE INDEX idx_muse_kb_doc_ver_doc ON muse_knowledge_document_version(tenant_id, document_id);
CREATE TRIGGER trg_muse_kb_doc_ver_updated_at BEFORE UPDATE ON muse_knowledge_document_version FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_knowledge_entity (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
kb_id BIGINT,
entity_type VARCHAR(50) NOT NULL,
normalized_name VARCHAR(200) NOT NULL,
scope VARCHAR(50) NOT NULL DEFAULT 'global',
description TEXT,
attributes JSONB,
source_snapshot_id BIGINT,
authorization_snapshot_id BIGINT,
source_status VARCHAR(30) NOT NULL DEFAULT 'active',
source_action_policy VARCHAR(30) NOT NULL DEFAULT 'allowed',
source_event_version INT,
lineage_payload JSONB,
status VARCHAR(20) NOT NULL DEFAULT 'active',
confidence DOUBLE PRECISION DEFAULT 1.0,
source_type VARCHAR(50),
source_id BIGINT,
command_id VARCHAR(120),
revision INT NOT NULL DEFAULT 1,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_knowledge_entity UNIQUE (tenant_id, work_id, entity_type, normalized_name, scope)
);
CREATE INDEX idx_muse_knowledge_entity_work_type ON muse_knowledge_entity(tenant_id, work_id, entity_type);
CREATE INDEX idx_muse_knowledge_entity_kb ON muse_knowledge_entity(tenant_id, kb_id);
CREATE UNIQUE INDEX uk_muse_knowledge_entity_command ON muse_knowledge_entity(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_knowledge_entity_updated_at BEFORE UPDATE ON muse_knowledge_entity FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_knowledge_relation (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
source_entity_id BIGINT NOT NULL,
target_entity_id BIGINT NOT NULL,
relation_type VARCHAR(50) NOT NULL,
description VARCHAR(500),
attributes JSONB,
source_status VARCHAR(30) NOT NULL DEFAULT 'active',
source_action_policy VARCHAR(30) NOT NULL DEFAULT 'allowed',
command_id VARCHAR(120),
revision INT NOT NULL DEFAULT 1,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_muse_knowledge_rel_work ON muse_knowledge_relation(tenant_id, work_id);
CREATE INDEX idx_muse_knowledge_rel_src ON muse_knowledge_relation(tenant_id, source_entity_id);
CREATE INDEX idx_muse_knowledge_rel_tgt ON muse_knowledge_relation(tenant_id, target_entity_id);
CREATE UNIQUE INDEX uk_muse_knowledge_rel_command ON muse_knowledge_relation(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_knowledge_relation_updated_at BEFORE UPDATE ON muse_knowledge_relation FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_knowledge_draft (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
entity_id BIGINT,
draft_type VARCHAR(30) NOT NULL DEFAULT 'entity',
target_object_id BIGINT,
proposed_changes JSONB,
draft_payload JSONB,
current_canonical_snapshot JSONB,
source_snapshot_id BIGINT,
authorization_snapshot_id BIGINT,
risk_marker_snapshot JSONB,
source_status VARCHAR(30),
source_action_policy VARCHAR(30),
status VARCHAR(20) NOT NULL DEFAULT 'pending',
confidence DOUBLE PRECISION,
source_type VARCHAR(50),
source_id BIGINT,
command_id VARCHAR(120),
revision INT NOT NULL DEFAULT 1,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_muse_knowledge_draft_work_status ON muse_knowledge_draft(tenant_id, work_id, status, create_time);
CREATE INDEX idx_muse_knowledge_draft_entity ON muse_knowledge_draft(tenant_id, entity_id);
CREATE UNIQUE INDEX uk_muse_knowledge_draft_command ON muse_knowledge_draft(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_knowledge_draft_updated_at BEFORE UPDATE ON muse_knowledge_draft FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE muse_knowledge_binding (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
work_id BIGINT NOT NULL,
kb_id BIGINT NOT NULL,
binding_type VARCHAR(50) NOT NULL DEFAULT 'read',
binding_scope VARCHAR(50) NOT NULL DEFAULT 'read',
binding_status VARCHAR(30) NOT NULL DEFAULT 'active',
source_snapshot_id BIGINT,
authorization_snapshot_id BIGINT,
source_version INT,
target_version INT,
command_id VARCHAR(120),
revision INT NOT NULL DEFAULT 1,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_knowledge_binding_work_kb UNIQUE (tenant_id, work_id, kb_id)
);
CREATE INDEX idx_muse_knowledge_binding_work ON muse_knowledge_binding(tenant_id, work_id);
CREATE INDEX idx_muse_knowledge_binding_kb ON muse_knowledge_binding(tenant_id, kb_id);
CREATE UNIQUE INDEX uk_muse_knowledge_binding_command ON muse_knowledge_binding(tenant_id, command_id) WHERE command_id IS NOT NULL;
CREATE TRIGGER trg_muse_knowledge_binding_updated_at BEFORE UPDATE ON muse_knowledge_binding FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

56
db/表映射.md Normal file
View File

@ -0,0 +1,56 @@
# muse-example 表 ↔ 主仓迁移来源映射A2 审查面)
> 口径(创始人拍板③ 2026-07-10主仓表**原样不改列**;实验私货全进 `example_*` 前缀。
> 建表方式:`db/ddl/` 下文件经 db skill `apply`,主仓部分为 `muse-cloud/sql/muse/` 原文拷贝或逐字摘录。
> 应用顺序V1 → V3 → V5 → 90-ALTER摘录 → V26 → 91-example。已于 2026-07-13 应用,共 **24 张表**
## 主仓一致表20 张)
| 表 | 来源迁移 | 叠加的 ALTER | 实验角色 |
|---|---|---|---|
| muse_content_work | V1 | — | 参考书/未来新作的作品行B1 导入) |
| muse_content_chapter | V1 | V26order 唯一键改 partial | 分章行B1 导入) |
| muse_content_block | V1 | V26同上 | 章正文载体(一章一 blockcontent_text |
| muse_content_block_source_attribution | V1 | V30authorization_snapshot_id→varchar(128) | 暂空置C 线来源归因 |
| muse_content_import_task | V1 | — | B1 导入任务审计 |
| muse_content_export_task | V1 | V9+4 列) | 暂空置C9 导出 |
| muse_content_command_log | V1 | — | 写命令幂等审计import/confirm 用) |
| muse_meta_schema | V3 | — | 23 型结构本体行A3 入库) |
| muse_meta_schema_version | V3 | V10active 唯一索引) | 型版本A3每型 v1 active |
| muse_meta_field | V3 | — | 逐型字段合同行A3 入库) |
| muse_meta_visibility_policy | V3 | — | aiContext 控制项落点A3 入库) |
| muse_meta_protection_node | V3 | V10+6 列) | 保护节点登记read-context/confirm/judge |
| muse_meta_function_chain | V3 | — | 功能链登记meta/chains 的库内影子,随需入库) |
| muse_knowledge_base | V5 | — | 私有参考书库 + 公共范式库kb 行) |
| muse_knowledge_document | V5 | — | 参考书原文档案指针storage_ref 指仓内路径) |
| muse_knowledge_document_version | V5 | — | 暂空置 |
| muse_knowledge_entity | V5 | — | **已确认**知识行B5 确认后落此) |
| muse_knowledge_relation | V5 | — | 知识行间关系(二轮再启用) |
| muse_knowledge_draft | V5 | V14两快照列→varchar(128) | **草稿**知识行B2 拆书产出落此) |
| muse_knowledge_binding | V5 | V14同上 | 作品↔库绑定C3 起用) |
## 实验私货表4 张,`db/ddl/91-example实验私货.sql`
| 表 | 用途 |
|---|---|
| example_reference_work | 参考书档案reference_work 型的库内实例载体):作者/章数对账/拆书范围与状态 |
| example_parse_task | 拆书任务状态机一章一行scaffold/pattern 两阶段状态——workflow 断点续跑与幂等 |
| example_parse_scaffold | 逐章脚手架逆推细纲35%+ 实体清单 JSONB |
| example_knowledge_embedding | 知识行嵌入边表vector(1024)+HNSW余弦content_hash 幂等,挂 draft 或 entity |
## 暂缓建表登记(主仓有、实验现阶段未建;需要时按原样加建)
| 迁移 | 表 | 暂缓原因 |
|---|---|---|
| V9 | muse_content_planning_section / governance_action | C2 规划确认时加建 planning_section |
| V10 | meta 治理 8 表command/audit/validation/impact/gray/chain_version/chain_slot/chain_node | 治理命令流实验不镜像;装配入库随阶段二 |
| V14 | knowledge RAGFlow/治理 14 表 | 实验用 pgvector 自持嵌入,不接 RAGFlow |
| V18/V21 | 两张 event_publish_outbox | 事件出箱不镜像 |
| V25/V28/V32/V36/V37 | field_snapshot / asset_use_precheck / block_revision_snapshot / ai_generated_fulltext / task 批次列 | 对应场景(用量投影/市场/版本快照/SSE 瞬态)不在实验闭环内 |
## 实验写入约定
- `tenant_id=1``creator='1'``owner_user_id=1`系统主账号——写入层统一给值列默认仍照主仓0/''),不改列。
- 公共范式的全局知识行:`work_id=0` + `scope='global'` + 挂 `kb_type='global'` 的库;参考书私有库 `kb_type='user'`
- 软删照主仓:`deleted=TRUE`,不物理删。
- 双轨对应B2 产出全落 `muse_knowledge_draft(status='pending')`B5 管理员确认(仅创始人触发)= draft 翻 `confirmed` + 落 `muse_knowledge_entity(status='active')`;丢弃= draft 翻 `ignored`