muse-agent-example/db/ddl/104-example-ai-flavor-cases.sql
zizi b0bc7a8745 框架: 技能按动作-对象重组 + 先审后入创作闭环
一、技能重组(动作-对象命名)
- 旧目录 clean/confirm/continuation/db/detect/embed/… 重组为
  clean-book-text/decide-candidate/write-next-chapter/access-database/
  check-content-consistency/embed-knowledge/…(git 识别为 rename,内容保持)
- agents/*.md、AGENTS.md/CLAUDE.md 收编、example_skill 登记表同步新名

二、先审后入创作闭环(本次核心)
正文接受从"机械门一过就写正典"改为"机械门+语义审查双通过+用户批准+单事务原子提交",
DB 级兜底,编排层跳步即被硬拒。
- candidate_cas.py + example_candidate_cas(109):持久化 CAS 状态链
- fact_delta.py + example_fact_delta/example_fact_ledger(106):结构化事实增量,
  模型只提六型闭集增量+正文证据引文,仅用户批准的增量随正文同事务入账本
- projection_registry.py + example_projection_run(107):投影登记与恢复
- acceptance_state.py:接受前置实时状态重读
- lesson_registry.py + example_lesson(108):经验升格链,禁止自动升格
- DDL 105:example_candidate 增 semantic_status/semantic_report_sha256
- write_canonical.accept:语义兜底+同事务合并增量+登记投影;
  run_writer_pipeline/persist_writer_run/run_writer_semantic_detector/step2 接入全链
- claude_runtime:兼容新 CLI modelUsage 信息字段

三、审查修复(独立子代理四维审查后)
- 事实增量 propose→approve 翻态正道,不撞唯一键
- 冻结配置探针重刷(CLI 2.1.211→2.1.231 漂移),profileSha256/adapterVersion 再登记
- 可视化合同悬空路径/五六空间矛盾、 SoT 旧技能名漂移、行尾空白清理

测试:离线 65 套 + 真实库集成 5 套(CAS/接受故障注入/事实增量/投影/经验升格)+ 回放 79 项全绿。
创作内容(docs/design、生成正文 artifacts)按"框架与创作分开"未入本提交。
2026-08-14 10:24:08 +08:00

143 lines
8.0 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- AI 味案例卡、来源重验证批次与逐卡回执。
-- agent-example 的 muse-example 是此资产的正式权威;离线 JSON 只是可复核的导入/恢复证据。
-- 案例卡是当前投影(可按评审更新);批次与回执是 append-only,保留每次检查历史。
-- 研究限定/未授权来源只允许 hash + 位置,数据库级约束禁止写入原文或升格。
CREATE TABLE IF NOT EXISTS example_ai_flavor_case (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
card_id VARCHAR(64) NOT NULL,
schema_version VARCHAR(64) NOT NULL,
card_type VARCHAR(64) NOT NULL,
state VARCHAR(20) NOT NULL,
label VARCHAR(20) NOT NULL,
layer VARCHAR(20) NOT NULL,
carrier VARCHAR(32) NOT NULL,
capture_mode VARCHAR(32) NOT NULL,
source_kind VARCHAR(32) NOT NULL,
source_license VARCHAR(32) NOT NULL,
source_sha256 VARCHAR(64) NOT NULL,
excerpt_sha256 VARCHAR(64) NOT NULL,
source_ref VARCHAR(512) NOT NULL DEFAULT '',
work_ref VARCHAR(256),
source_location JSONB NOT NULL,
surface_location JSONB,
excerpt TEXT NOT NULL DEFAULT '',
context TEXT NOT NULL DEFAULT '',
observation JSONB NOT NULL,
feedback JSONB,
review JSONB,
rule_candidate_ids JSONB NOT NULL DEFAULT '[]'::jsonb,
inventory_ref VARCHAR(512),
inventory_sha256 VARCHAR(64),
creator VARCHAR(64) NOT NULL DEFAULT '1',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '1',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 1,
CONSTRAINT uk_example_ai_flavor_case UNIQUE (tenant_id, card_id),
CONSTRAINT chk_example_ai_flavor_case_schema CHECK (schema_version = 'ai-flavor-case-v1'),
CONSTRAINT chk_example_ai_flavor_case_type CHECK (card_type = 'ai_flavor_case'),
CONSTRAINT chk_example_ai_flavor_case_state CHECK (state IN ('shadow','canonical','rejected','archived')),
CONSTRAINT chk_example_ai_flavor_case_label CHECK (label IN ('unclassified','sf','snf','boundary','regression')),
CONSTRAINT chk_example_ai_flavor_case_layer CHECK (layer IN ('mechanical','lexical','structural','density','semantic','unknown')),
CONSTRAINT chk_example_ai_flavor_case_carrier CHECK (carrier IN ('narration','dialogue','monologue','in_text_carrier','mixed','unknown')),
CONSTRAINT chk_example_ai_flavor_case_capture CHECK (capture_mode IN ('backfill','live_feedback','synthetic','review_import')),
CONSTRAINT chk_example_ai_flavor_case_source_kind CHECK (source_kind IN ('existing_work','creation_feedback','synthetic','public_domain')),
CONSTRAINT chk_example_ai_flavor_case_license CHECK (source_license IN ('owned','licensed','public_domain','research_only','unauthorized','synthetic')),
CONSTRAINT chk_example_ai_flavor_case_id CHECK (card_id ~ '^case-[a-z0-9]{20}$'),
CONSTRAINT chk_example_ai_flavor_case_source_sha CHECK (source_sha256 ~ '^[0-9a-f]{64}$'),
CONSTRAINT chk_example_ai_flavor_case_excerpt_sha CHECK (excerpt_sha256 ~ '^[0-9a-f]{64}$'),
CONSTRAINT chk_example_ai_flavor_case_inventory_sha CHECK (inventory_sha256 IS NULL OR inventory_sha256 ~ '^[0-9a-f]{64}$'),
CONSTRAINT chk_example_ai_flavor_case_json_arrays CHECK (jsonb_typeof(rule_candidate_ids) = 'array'),
CONSTRAINT chk_example_ai_flavor_case_research_only CHECK (
source_license NOT IN ('research_only','unauthorized')
OR (excerpt = '' AND context = '' AND state = 'shadow')
)
);
CREATE INDEX IF NOT EXISTS idx_example_ai_flavor_case_work_state
ON example_ai_flavor_case(tenant_id, work_ref, state) WHERE deleted = FALSE;
CREATE INDEX IF NOT EXISTS idx_example_ai_flavor_case_pattern
ON example_ai_flavor_case(tenant_id, ((observation->>'pattern_key'))) WHERE deleted = FALSE;
CREATE INDEX IF NOT EXISTS idx_example_ai_flavor_case_source_sha
ON example_ai_flavor_case(tenant_id, source_sha256);
CREATE OR REPLACE TRIGGER trg_example_ai_flavor_case_updated_at
BEFORE UPDATE ON example_ai_flavor_case FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE IF NOT EXISTS example_ai_flavor_revalidation_batch (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
batch_ref VARCHAR(512) NOT NULL,
report_sha256 VARCHAR(64) NOT NULL,
schema_version VARCHAR(64) NOT NULL,
checked_on DATE NOT NULL,
source_root_ref VARCHAR(512),
usable BOOLEAN NOT NULL,
totals JSONB NOT NULL,
works JSONB NOT NULL DEFAULT '[]'::jsonb,
report_path VARCHAR(512),
creator VARCHAR(64) NOT NULL DEFAULT '1',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
tenant_id BIGINT NOT NULL DEFAULT 1,
CONSTRAINT uk_example_ai_flavor_revalidation_batch UNIQUE (tenant_id, report_sha256),
CONSTRAINT chk_example_ai_flavor_revalidation_batch_sha CHECK (report_sha256 ~ '^[0-9a-f]{64}$'),
CONSTRAINT chk_example_ai_flavor_revalidation_batch_schema CHECK (schema_version = 'ai-flavor-revalidation-v1'),
CONSTRAINT chk_example_ai_flavor_revalidation_batch_json CHECK (
jsonb_typeof(totals) = 'object' AND jsonb_typeof(works) = 'array'
)
);
CREATE INDEX IF NOT EXISTS idx_example_ai_flavor_revalidation_batch_date
ON example_ai_flavor_revalidation_batch(tenant_id, checked_on DESC, id DESC);
CREATE TABLE IF NOT EXISTS example_ai_flavor_revalidation (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
batch_id BIGINT NOT NULL,
card_id VARCHAR(64) NOT NULL,
work_ref VARCHAR(256),
source_ref VARCHAR(512) NOT NULL DEFAULT '',
expected_source_sha256 VARCHAR(64) NOT NULL,
actual_source_sha256 VARCHAR(64),
status VARCHAR(20) NOT NULL,
reason VARCHAR(64) NOT NULL DEFAULT '',
checked_on DATE NOT NULL,
creator VARCHAR(64) NOT NULL DEFAULT '1',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
tenant_id BIGINT NOT NULL DEFAULT 1,
CONSTRAINT uk_example_ai_flavor_revalidation UNIQUE (tenant_id, batch_id, card_id),
CONSTRAINT chk_example_ai_flavor_revalidation_card CHECK (card_id ~ '^case-[a-z0-9]{20}$'),
CONSTRAINT chk_example_ai_flavor_revalidation_expected_sha CHECK (expected_source_sha256 ~ '^[0-9a-f]{64}$'),
CONSTRAINT chk_example_ai_flavor_revalidation_actual_sha CHECK (actual_source_sha256 IS NULL OR actual_source_sha256 ~ '^[0-9a-f]{64}$'),
CONSTRAINT chk_example_ai_flavor_revalidation_status CHECK (status IN ('verified','stale','unavailable','card_mismatch'))
);
CREATE INDEX IF NOT EXISTS idx_example_ai_flavor_revalidation_card
ON example_ai_flavor_revalidation(tenant_id, card_id, checked_on DESC);
CREATE INDEX IF NOT EXISTS idx_example_ai_flavor_revalidation_status
ON example_ai_flavor_revalidation(tenant_id, status, checked_on DESC);
CREATE INDEX IF NOT EXISTS idx_example_ai_flavor_revalidation_batch
ON example_ai_flavor_revalidation(tenant_id, batch_id);
CREATE OR REPLACE FUNCTION reject_example_ai_flavor_revalidation_mutation()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
RAISE EXCEPTION '% 是 append-only 表,禁止 UPDATE/DELETE', TG_TABLE_NAME;
END;
$$;
CREATE OR REPLACE TRIGGER trg_example_ai_flavor_revalidation_batch_append_only
BEFORE UPDATE OR DELETE ON example_ai_flavor_revalidation_batch
FOR EACH ROW EXECUTE FUNCTION reject_example_ai_flavor_revalidation_mutation();
CREATE OR REPLACE TRIGGER trg_example_ai_flavor_revalidation_append_only
BEFORE UPDATE OR DELETE ON example_ai_flavor_revalidation
FOR EACH ROW EXECUTE FUNCTION reject_example_ai_flavor_revalidation_mutation();
CREATE OR REPLACE TRIGGER trg_example_ai_flavor_revalidation_batch_no_truncate
BEFORE TRUNCATE ON example_ai_flavor_revalidation_batch
FOR EACH STATEMENT EXECUTE FUNCTION example_reject_truncate();
CREATE OR REPLACE TRIGGER trg_example_ai_flavor_revalidation_no_truncate
BEFORE TRUNCATE ON example_ai_flavor_revalidation
FOR EACH STATEMENT EXECUTE FUNCTION example_reject_truncate();
GRANT SELECT ON example_ai_flavor_case TO muse_read;
GRANT SELECT ON example_ai_flavor_revalidation_batch TO muse_read;
GRANT SELECT ON example_ai_flavor_revalidation TO muse_read;