291 lines
14 KiB
SQL
291 lines
14 KiB
SQL
-- W05:持久任务、步骤、尝试、独立作用域租约和有序事件。
|
||
-- W06 模型预算与 W08 原文生命周期随所属实现接入;仅用于尚未冻结的开发基线。
|
||
DO $migration$
|
||
DECLARE
|
||
namespace text;
|
||
BEGIN
|
||
FOREACH namespace IN ARRAY ARRAY['public', 'evaluation'] LOOP
|
||
EXECUTE format($ddl$
|
||
CREATE TABLE %1$I.muse_task (
|
||
task_id uuid PRIMARY KEY,
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
command_id text NOT NULL,
|
||
author_id text NOT NULL,
|
||
request_hash text NOT NULL,
|
||
frozen_input jsonb NOT NULL,
|
||
flow_id text NOT NULL,
|
||
flow_version text NOT NULL,
|
||
flow_snapshot jsonb NOT NULL,
|
||
state text NOT NULL CHECK (state IN ('queued','running','paused','reconciling','failed','cancelled','completed')),
|
||
scope_key text,
|
||
scope_generation bigint,
|
||
last_sequence bigint NOT NULL DEFAULT 0,
|
||
created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
updated_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
UNIQUE (run_purpose, author_id, command_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_task_control (
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
author_id text NOT NULL,
|
||
command_id text NOT NULL,
|
||
task_id uuid NOT NULL REFERENCES %1$I.muse_task(task_id),
|
||
request_hash text NOT NULL,
|
||
receipt jsonb,
|
||
PRIMARY KEY (run_purpose, author_id, command_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_step (
|
||
task_id uuid NOT NULL REFERENCES %1$I.muse_task(task_id),
|
||
step_id text NOT NULL,
|
||
processor_id text NOT NULL,
|
||
processor_version text NOT NULL,
|
||
dependencies text[] NOT NULL,
|
||
state text NOT NULL CHECK (state IN ('pending','running','completed','failed','unknown')),
|
||
current_attempt uuid,
|
||
checkpoint jsonb NOT NULL DEFAULT '{}',
|
||
result jsonb,
|
||
PRIMARY KEY (task_id, step_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_attempt (
|
||
attempt_id uuid PRIMARY KEY,
|
||
task_id uuid NOT NULL,
|
||
step_id text NOT NULL,
|
||
worker_id text NOT NULL,
|
||
lease_token uuid NOT NULL,
|
||
lease_until timestamptz NOT NULL,
|
||
scope_generation bigint,
|
||
heartbeat_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
state text NOT NULL CHECK (state IN ('running','expired','paused','cancelled','completed','failed','unknown')),
|
||
call_state text NOT NULL DEFAULT 'not_sent' CHECK (call_state IN ('not_sent','sent','unknown','saved')),
|
||
call_reference text,
|
||
result jsonb,
|
||
failure_code text,
|
||
created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
FOREIGN KEY (task_id, step_id) REFERENCES %1$I.muse_step(task_id, step_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_task_scope_lease (
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
scope_key text NOT NULL,
|
||
holder_task_id uuid,
|
||
generation bigint NOT NULL CHECK (generation > 0),
|
||
lease_until timestamptz NOT NULL,
|
||
PRIMARY KEY (run_purpose, scope_key)
|
||
);
|
||
CREATE TABLE %1$I.muse_task_event (
|
||
event_id uuid PRIMARY KEY,
|
||
task_id uuid NOT NULL REFERENCES %1$I.muse_task(task_id),
|
||
step_id text,
|
||
attempt_id uuid,
|
||
sequence bigint NOT NULL,
|
||
event_type text NOT NULL,
|
||
occurred_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
payload_version integer NOT NULL,
|
||
payload jsonb NOT NULL,
|
||
payload_hash text NOT NULL,
|
||
UNIQUE(task_id, sequence)
|
||
);
|
||
CREATE INDEX ON %1$I.muse_task (run_purpose, state, created_at);
|
||
CREATE INDEX ON %1$I.muse_step (state, task_id);
|
||
CREATE INDEX ON %1$I.muse_attempt (task_id, state, lease_until);
|
||
$ddl$, namespace);
|
||
END LOOP;
|
||
END
|
||
$migration$;
|
||
|
||
-- W06 预算与配置:额度账户串行化预留,金额事实留在逐调用账本。
|
||
-- W08 原文:授权和租约先持久化,完整归档事务同时写入清单与字节。
|
||
DO $raw_lifecycle$
|
||
DECLARE namespace text;
|
||
BEGIN
|
||
FOREACH namespace IN ARRAY ARRAY['public', 'evaluation'] LOOP
|
||
EXECUTE format($ddl$
|
||
CREATE TABLE %1$I.muse_raw_namespace (
|
||
singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
|
||
namespace_id uuid NOT NULL DEFAULT gen_random_uuid()
|
||
);
|
||
INSERT INTO %1$I.muse_raw_namespace (singleton) VALUES (true);
|
||
CREATE TABLE %1$I.muse_raw_orphan_cleanup (
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
object_id uuid NOT NULL,
|
||
receipt_id uuid NOT NULL DEFAULT gen_random_uuid(),
|
||
state text NOT NULL CHECK (state IN ('pending','completed')),
|
||
removed boolean,
|
||
completed_at timestamptz,
|
||
PRIMARY KEY (run_purpose,object_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_raw_authorization (
|
||
authorization_id uuid PRIMARY KEY,
|
||
task_id uuid NOT NULL REFERENCES %1$I.muse_task(task_id),
|
||
command_id text NOT NULL,
|
||
approved_by text NOT NULL,
|
||
source_version text NOT NULL,
|
||
content_hashes text[] NOT NULL CHECK (cardinality(content_hashes)>0),
|
||
purpose text NOT NULL,
|
||
retention_mode text NOT NULL CHECK (retention_mode IN ('temporary','archive','persistent')),
|
||
approved_at timestamptz NOT NULL,
|
||
valid_until timestamptz NOT NULL,
|
||
request_hash text NOT NULL,
|
||
revoked boolean NOT NULL DEFAULT false,
|
||
call_id text,
|
||
call_request_hash text,
|
||
response_hash text,
|
||
parent_authorization_id uuid REFERENCES %1$I.muse_raw_authorization(authorization_id),
|
||
attempt_id uuid REFERENCES %1$I.muse_attempt(attempt_id),
|
||
derivation_kind text CHECK (derivation_kind IN ('model','tool')),
|
||
evidence_refs uuid[] NOT NULL DEFAULT '{}',
|
||
CHECK ((call_id IS NULL) = (call_request_hash IS NULL)),
|
||
CHECK (response_hash IS NULL OR call_id IS NOT NULL),
|
||
UNIQUE(task_id,command_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_role_session_authorization (
|
||
authorization_id uuid PRIMARY KEY REFERENCES %1$I.muse_raw_authorization(authorization_id),
|
||
step_id text NOT NULL,
|
||
stage text NOT NULL,
|
||
initial_request_hash text NOT NULL,
|
||
frozen_input_hash text NOT NULL,
|
||
max_model_calls integer NOT NULL CHECK (max_model_calls>0),
|
||
max_tool_calls integer NOT NULL CHECK (max_tool_calls>=0),
|
||
policy_hash text NOT NULL
|
||
);
|
||
CREATE TABLE %1$I.muse_raw_lease (
|
||
lease_id uuid PRIMARY KEY,
|
||
task_id uuid NOT NULL REFERENCES %1$I.muse_task(task_id),
|
||
authorization_id uuid NOT NULL REFERENCES %1$I.muse_raw_authorization(authorization_id),
|
||
command_id text NOT NULL,
|
||
created_at timestamptz NOT NULL,
|
||
retain_until timestamptz NOT NULL,
|
||
state text NOT NULL CHECK (state IN ('open','closed','migrating','migrated')),
|
||
archive_id uuid,
|
||
archive_authorization_id uuid REFERENCES %1$I.muse_raw_authorization(authorization_id),
|
||
cleanup_receipt uuid,
|
||
failure_code text,
|
||
UNIQUE(task_id,command_id),
|
||
CHECK (retain_until>created_at AND retain_until<=created_at+interval '24 hours')
|
||
);
|
||
CREATE TABLE %1$I.muse_raw_archive (
|
||
archive_id uuid PRIMARY KEY,
|
||
lease_id uuid UNIQUE REFERENCES %1$I.muse_raw_lease(lease_id),
|
||
legacy_ref text UNIQUE,
|
||
legacy_manifest jsonb,
|
||
CHECK ((lease_id IS NULL) <> (legacy_ref IS NULL)),
|
||
authorization_id uuid NOT NULL REFERENCES %1$I.muse_raw_authorization(authorization_id),
|
||
tree_hash text NOT NULL,
|
||
entry_count integer NOT NULL CHECK (entry_count>0),
|
||
total_bytes bigint NOT NULL CHECK (total_bytes>=0),
|
||
receipt_id uuid NOT NULL,
|
||
created_at timestamptz NOT NULL
|
||
);
|
||
CREATE TABLE %1$I.muse_raw_archive_item (
|
||
archive_id uuid NOT NULL REFERENCES %1$I.muse_raw_archive(archive_id),
|
||
content_hash text NOT NULL,
|
||
content bytea NOT NULL,
|
||
PRIMARY KEY(archive_id,content_hash)
|
||
);
|
||
CREATE TABLE %1$I.muse_runtime_evidence (
|
||
evidence_id uuid PRIMARY KEY,
|
||
task_id uuid NOT NULL REFERENCES %1$I.muse_task(task_id),
|
||
attempt_id uuid NOT NULL REFERENCES %1$I.muse_attempt(attempt_id),
|
||
kind text NOT NULL CHECK (kind IN ('model_input','model_response','tool_result','failure')),
|
||
reference_id text NOT NULL,
|
||
content_hash text NOT NULL,
|
||
content bytea,
|
||
authorization_id uuid REFERENCES %1$I.muse_raw_authorization(authorization_id),
|
||
outcome text NOT NULL CHECK (outcome IN ('completed','failed','partial')),
|
||
metadata jsonb NOT NULL,
|
||
revision integer NOT NULL DEFAULT 1,
|
||
created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
UNIQUE(attempt_id,kind,reference_id),
|
||
CHECK (content IS NULL OR authorization_id IS NOT NULL)
|
||
);
|
||
$ddl$, namespace);
|
||
EXECUTE format('REVOKE INSERT,UPDATE,DELETE ON %I.muse_raw_namespace FROM muse_app,muse_eval', namespace);
|
||
END LOOP;
|
||
END
|
||
$raw_lifecycle$;
|
||
|
||
DO $budget_config$
|
||
DECLARE
|
||
namespace text;
|
||
BEGIN
|
||
FOREACH namespace IN ARRAY ARRAY['public', 'evaluation'] LOOP
|
||
EXECUTE format($ddl$
|
||
CREATE TABLE %1$I.muse_budget_account (
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
account_id text NOT NULL,
|
||
policy_version text NOT NULL,
|
||
policy jsonb NOT NULL,
|
||
policy_hash text NOT NULL,
|
||
PRIMARY KEY (run_purpose, account_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_task_budget (
|
||
task_id uuid PRIMARY KEY REFERENCES %1$I.muse_task(task_id),
|
||
account_id text NOT NULL,
|
||
plan jsonb NOT NULL,
|
||
plan_hash text NOT NULL,
|
||
stopped boolean NOT NULL DEFAULT false
|
||
);
|
||
CREATE TABLE %1$I.muse_budget_reservation (
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
call_id text NOT NULL,
|
||
account_id text NOT NULL,
|
||
task_id uuid NOT NULL REFERENCES %1$I.muse_task(task_id),
|
||
attempt_id uuid NOT NULL REFERENCES %1$I.muse_attempt(attempt_id),
|
||
role_id text NOT NULL,
|
||
request_hash text NOT NULL,
|
||
state text NOT NULL CHECK (state IN ('reserved','in_flight','unknown','settled','released')),
|
||
reserved_amount numeric(24,6) NOT NULL CHECK (reserved_amount >= 0),
|
||
actual_amount numeric(24,6) CHECK (actual_amount >= 0),
|
||
window_start timestamptz NOT NULL,
|
||
window_end timestamptz NOT NULL,
|
||
expires_at timestamptz NOT NULL,
|
||
sent_at timestamptz,
|
||
receipt_id text,
|
||
reason text,
|
||
over_budget boolean NOT NULL DEFAULT false,
|
||
PRIMARY KEY (run_purpose, call_id),
|
||
CHECK ((state = 'settled') = (actual_amount IS NOT NULL))
|
||
);
|
||
CREATE INDEX ON %1$I.muse_budget_reservation (run_purpose,account_id,window_start);
|
||
CREATE INDEX ON %1$I.muse_budget_reservation (task_id,role_id);
|
||
CREATE TABLE %1$I.muse_runtime_config_version (
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
config_id text NOT NULL,
|
||
version text NOT NULL,
|
||
content jsonb NOT NULL,
|
||
content_hash text NOT NULL,
|
||
created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
PRIMARY KEY (run_purpose,config_id,version)
|
||
);
|
||
CREATE TABLE %1$I.muse_runtime_config_validation (
|
||
receipt_id uuid PRIMARY KEY,
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
config_id text NOT NULL,
|
||
version text NOT NULL,
|
||
content_hash text NOT NULL,
|
||
validator_id text NOT NULL,
|
||
evidence_refs jsonb NOT NULL,
|
||
validated_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||
FOREIGN KEY (run_purpose,config_id,version)
|
||
REFERENCES %1$I.muse_runtime_config_version(run_purpose,config_id,version)
|
||
);
|
||
CREATE TABLE %1$I.muse_runtime_config_active (
|
||
run_purpose public.muse_purpose NOT NULL,
|
||
config_id text NOT NULL,
|
||
version text,
|
||
validation_receipt uuid REFERENCES %1$I.muse_runtime_config_validation(receipt_id),
|
||
approval_ref text,
|
||
generation bigint NOT NULL DEFAULT 0,
|
||
PRIMARY KEY (run_purpose,config_id)
|
||
);
|
||
CREATE TABLE %1$I.muse_task_config_binding (
|
||
task_id uuid PRIMARY KEY REFERENCES %1$I.muse_task(task_id),
|
||
config_id text NOT NULL,
|
||
version text NOT NULL,
|
||
content_hash text NOT NULL,
|
||
content jsonb NOT NULL,
|
||
validation_receipt uuid NOT NULL REFERENCES %1$I.muse_runtime_config_validation(receipt_id)
|
||
);
|
||
$ddl$, namespace);
|
||
END LOOP;
|
||
END
|
||
$budget_config$;
|