Implement Scene 7 evidence goal flow

This commit is contained in:
2026-08-22 16:02:42 +02:00
parent 34aa23237e
commit a7f99a2a39
31 changed files with 1620 additions and 52 deletions
+31
View File
@@ -0,0 +1,31 @@
-- Data-defined level success conditions. Goals and their requirements belong to
-- clonable boards; completion is derived from the mutable level's existing flags.
CREATE TABLE osint.level_goals (
id UUID PRIMARY KEY,
board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
origin_goal_id UUID REFERENCES osint.level_goals(id) ON DELETE SET NULL,
goal_key TEXT NOT NULL CHECK (goal_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
title TEXT NOT NULL CHECK (char_length(btrim(title)) BETWEEN 1 AND 200),
instructions TEXT NOT NULL DEFAULT '',
completion_message TEXT NOT NULL DEFAULT '',
enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (board_id,id),
UNIQUE (board_id,goal_key)
);
CREATE INDEX level_goals_board_enabled_idx ON osint.level_goals (board_id,created_at,id) WHERE enabled;
CREATE TABLE osint.level_goal_flag_requirements (
board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
goal_id UUID NOT NULL REFERENCES osint.level_goals(id) ON DELETE CASCADE,
flag_key TEXT NOT NULL CHECK (flag_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
PRIMARY KEY (goal_id,flag_key),
FOREIGN KEY (board_id,goal_id) REFERENCES osint.level_goals(board_id,id) ON DELETE CASCADE
);
CREATE INDEX level_goal_flag_requirements_board_flag_idx
ON osint.level_goal_flag_requirements (board_id,flag_key);
COMMENT ON TABLE osint.level_goals IS 'Clonable, authored player objectives. Completion is derived from required flags on a mutable level.';
COMMENT ON TABLE osint.level_goal_flag_requirements IS 'All listed level flags must be earned for the owning goal to be complete.';
@@ -0,0 +1,65 @@
-- Optional semantic fallback for evidence that does not match an authored source
-- fingerprint. Rules clone with boards; evaluations and their flag provenance
-- belong to one mutable level/document.
CREATE TABLE osint.evidence_semantic_rules (
id UUID PRIMARY KEY,
board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
origin_rule_id UUID REFERENCES osint.evidence_semantic_rules(id) ON DELETE SET NULL,
goal_id UUID NOT NULL REFERENCES osint.level_goals(id) ON DELETE CASCADE,
name TEXT NOT NULL CHECK (char_length(btrim(name)) BETWEEN 1 AND 160),
target_subject TEXT NOT NULL CHECK (char_length(btrim(target_subject)) BETWEEN 1 AND 300),
related_subject TEXT CHECK (related_subject IS NULL OR char_length(btrim(related_subject)) BETWEEN 1 AND 300),
assertion_text TEXT NOT NULL CHECK (char_length(btrim(assertion_text)) BETWEEN 1 AND 2000),
success_flag_key TEXT NOT NULL CHECK (success_flag_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
related_flag_key TEXT CHECK (related_flag_key IS NULL OR related_flag_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
minimum_confidence NUMERIC(4,3) NOT NULL DEFAULT 0.850 CHECK (minimum_confidence BETWEEN 0.500 AND 1),
evaluator_version TEXT NOT NULL DEFAULT 'evidence_claim_v1' CHECK (char_length(btrim(evaluator_version)) BETWEEN 1 AND 100),
enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (board_id,id),
UNIQUE (board_id,name),
FOREIGN KEY (board_id,goal_id) REFERENCES osint.level_goals(board_id,id) ON DELETE CASCADE
);
CREATE INDEX evidence_semantic_rules_board_enabled_idx
ON osint.evidence_semantic_rules (board_id,created_at,id) WHERE enabled;
CREATE TABLE osint.evidence_semantic_evaluations (
id UUID PRIMARY KEY,
level_id UUID NOT NULL,
board_id UUID NOT NULL,
document_exhibit_id UUID NOT NULL REFERENCES osint.document_exhibits(exhibit_id) ON DELETE CASCADE,
extraction_id UUID NOT NULL REFERENCES osint.asset_text_extractions(id) ON DELETE CASCADE,
rule_id UUID NOT NULL,
evaluator_version TEXT NOT NULL,
provider TEXT NOT NULL,
model TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('pending','succeeded','failed')),
subject TEXT CHECK (subject IS NULL OR subject IN ('target','related','ambiguous','neither')),
supports_claim BOOLEAN,
evidence_excerpt TEXT NOT NULL DEFAULT '',
confidence NUMERIC(4,3) CHECK (confidence IS NULL OR confidence BETWEEN 0 AND 1),
failure_code TEXT,
attempt_count SMALLINT NOT NULL DEFAULT 1 CHECK (attempt_count > 0),
evaluated_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
FOREIGN KEY (level_id,board_id) REFERENCES osint.levels(id,board_id) ON DELETE CASCADE,
FOREIGN KEY (board_id,document_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE,
FOREIGN KEY (board_id,rule_id) REFERENCES osint.evidence_semantic_rules(board_id,id) ON DELETE CASCADE,
UNIQUE (level_id,document_exhibit_id,rule_id,evaluator_version),
CHECK (status <> 'succeeded' OR (subject IS NOT NULL AND supports_claim IS NOT NULL AND confidence IS NOT NULL)),
CHECK (status <> 'failed' OR failure_code IS NOT NULL)
);
CREATE INDEX evidence_semantic_evaluations_level_idx
ON osint.evidence_semantic_evaluations (level_id,updated_at DESC);
ALTER TABLE osint.level_flags
ADD COLUMN awarded_by_semantic_evaluation_id UUID REFERENCES osint.evidence_semantic_evaluations(id) ON DELETE SET NULL,
ADD CONSTRAINT level_flags_single_evidence_provenance CHECK (
num_nonnulls(awarded_by_evidence_match_id,awarded_by_semantic_evaluation_id) <= 1
);
COMMENT ON TABLE osint.evidence_semantic_rules IS 'Clonable evidence-only claim classifiers used after deterministic source matching misses.';
COMMENT ON TABLE osint.evidence_semantic_evaluations IS 'Idempotent, auditable semantic verdicts for one level document and authored rule.';
@@ -0,0 +1,10 @@
-- Optional author-facing provenance for a deterministic source fingerprint.
-- Players prove provenance through the source text and are not required to paste
-- this URL.
ALTER TABLE osint.evidence_match_rules
ADD COLUMN source_label TEXT,
ADD COLUMN source_uri TEXT;
COMMENT ON COLUMN osint.evidence_match_rules.source_label IS 'Author-facing label for the known source represented by this fingerprint.';
COMMENT ON COLUMN osint.evidence_match_rules.source_uri IS 'Author-facing canonical source URI; never a required player input.';