-- B06 只登记作者控制的有限返修会话、轮任务引用和选择;实际模型任务与候选仍归 S02/B05。 CREATE TABLE public.muse_revision_session ( session_id uuid PRIMARY KEY, author_id text NOT NULL, create_command_id text NOT NULL, request_hash text NOT NULL CHECK(request_hash ~ '^[0-9a-f]{64}$'), work_id text NOT NULL REFERENCES public.muse_work(work_id), chapter_id text NOT NULL REFERENCES public.muse_chapter(chapter_id), branch_id text NOT NULL, original_revision bigint NOT NULL CHECK(original_revision > 0), original_document_hash text NOT NULL CHECK(original_document_hash ~ '^[0-9a-f]{64}$'), source_kind text NOT NULL CHECK(source_kind IN ('diagnosis','selection')), basis_hash text NOT NULL CHECK(basis_hash ~ '^[0-9a-f]{64}$'), "authorization" jsonb NOT NULL CHECK(jsonb_typeof("authorization") = 'object'), authorization_hash text NOT NULL CHECK(authorization_hash ~ '^[0-9a-f]{64}$'), config_id text NOT NULL, max_rounds integer NOT NULL CHECK(max_rounds BETWEEN 1 AND 5), current_round integer NOT NULL DEFAULT 1 CHECK(current_round BETWEEN 1 AND 5), state text NOT NULL CHECK(state IN ('preparing','running','awaiting_author','closed')), stop_reason text, stop_detail text, author_choice text CHECK(author_choice IN ('original','candidate')), selected_candidate_id uuid REFERENCES public.muse_writing_candidate(candidate_id), created_at timestamptz NOT NULL DEFAULT clock_timestamp(), updated_at timestamptz NOT NULL DEFAULT clock_timestamp(), UNIQUE(author_id,create_command_id), UNIQUE(session_id,author_id), CHECK(current_round <= max_rounds), CHECK((state = 'closed') = (stop_reason IS NOT NULL)), CHECK( (author_choice IS NULL AND selected_candidate_id IS NULL) OR (author_choice = 'original' AND selected_candidate_id IS NULL) OR (author_choice = 'candidate' AND selected_candidate_id IS NOT NULL) ) ); CREATE TABLE public.muse_revision_round ( session_id uuid NOT NULL REFERENCES public.muse_revision_session(session_id), round_number integer NOT NULL CHECK(round_number BETWEEN 1 AND 5), task_command_id text NOT NULL UNIQUE, task_request_hash text NOT NULL CHECK(task_request_hash ~ '^[0-9a-f]{64}$'), task_id uuid UNIQUE REFERENCES public.muse_task(task_id), state text NOT NULL CHECK(state IN ('preparing','running','candidate','original','rejected')), outcome text CHECK(outcome IN ('candidate','original','rejected')), candidate_id uuid REFERENCES public.muse_writing_candidate(candidate_id), created_at timestamptz NOT NULL DEFAULT clock_timestamp(), updated_at timestamptz NOT NULL DEFAULT clock_timestamp(), PRIMARY KEY(session_id,round_number), CHECK((task_id IS NULL) = (state = 'preparing')), CHECK((outcome IS NULL) = (state IN ('preparing','running'))), CHECK((outcome = 'candidate') = (candidate_id IS NOT NULL)) ); CREATE TABLE public.muse_revision_session_action ( action_id uuid PRIMARY KEY, session_id uuid NOT NULL REFERENCES public.muse_revision_session(session_id), author_id text NOT NULL, command_id text NOT NULL, expected_round integer NOT NULL CHECK(expected_round BETWEEN 1 AND 5), candidate_id uuid NOT NULL REFERENCES public.muse_writing_candidate(candidate_id), choice text NOT NULL CHECK(choice IN ('original','candidate','retry')), request_hash text NOT NULL CHECK(request_hash ~ '^[0-9a-f]{64}$'), created_at timestamptz NOT NULL DEFAULT clock_timestamp(), UNIQUE(author_id,command_id), FOREIGN KEY(session_id,author_id) REFERENCES public.muse_revision_session(session_id,author_id) ); CREATE TRIGGER muse_revision_session_action_immutable BEFORE UPDATE OR DELETE ON public.muse_revision_session_action FOR EACH ROW EXECUTE FUNCTION public.muse_guard_literary_history(); REVOKE ALL ON public.muse_revision_session,public.muse_revision_round, public.muse_revision_session_action FROM PUBLIC,muse_app,muse_eval; GRANT SELECT,INSERT ON public.muse_revision_session,public.muse_revision_round TO muse_app; GRANT UPDATE(current_round,state,stop_reason,stop_detail,author_choice, selected_candidate_id,updated_at) ON public.muse_revision_session TO muse_app; GRANT UPDATE(task_id,state,outcome,candidate_id,updated_at) ON public.muse_revision_round TO muse_app; GRANT SELECT,INSERT ON public.muse_revision_session_action TO muse_app;