generated from coulomb/repo-seed
feat(WP-0012): IHF Phase 11 — Advanced AI Federation
Some checks failed
Test / test (push) Has been cancelled
Some checks failed
Test / test (push) Has been cancelled
- Schema: AgentRegistration, ModelRoutingPolicy, AgentDelegation, CollectiveProposal, CollectiveProposalContribution, AiGovernancePolicy, AgentPerformanceRecord + ALTER TABLE agent_proposals (migration 1744156800; CHECK constraints on trust_level, status, consensus_status — GAAF compliant) - Bridge: scripts/llm_bridge.py (llm-connect subprocess seam) + Application/Helper/AgentBridge.hs (callBridge, callAgent, checkGovernancePolicy, jsonArrayTexts) - Routing: Application/Helper/ModelRouter.hs (resolveAgent, resolveAllAgents) + ModelRoutingPolicies CRUD - Registry: AgentRegistrations CRUD (Index/Show/New/Edit/Performance), DeactivateAgentAction, ComputeAgentPerformanceAction - Delegation: AgentDelegations controller + views, DelegateSubtaskAction with token budget enforcement at bridge call time - Collective: CollectiveProposals controller + views, CreateCollectiveProposalAction (fan-out → synthesis → consensus detection) - Governance: AiGovernancePolicies CRUD + ToggleAiGovernancePolicyAction; checkGovernancePolicy enforced at all 4 Phase 5 invocation points - Phase 5 wiring: replaced callClaudeApi in Widgets, DecisionRecords, RequirementCandidates with resolveAgent + callAgent + token tracking - llm-connect feature requests: ~/llm-connect/FEATURE_REQUESTS.md (FR-1 HTTP serve, FR-2 RoutingPolicy, FR-3 async, FR-4 BudgetTracker) - GAAF scorecard: 3.61 (up from 3.56); Functional 3.4→3.6, Extensions 3.8→3.9 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
116
Application/Helper/AgentBridge.hs
Normal file
116
Application/Helper/AgentBridge.hs
Normal file
@@ -0,0 +1,116 @@
|
||||
module Application.Helper.AgentBridge where
|
||||
|
||||
-- IHF Phase 11 — Advanced AI Federation (IHUB-WP-0012)
|
||||
-- Haskell wrapper around scripts/llm_bridge.py (llm-connect subprocess bridge).
|
||||
|
||||
import IHP.Prelude
|
||||
import IHP.ControllerPrelude
|
||||
import Data.Aeson (object, (.=), encode, decode, Value, FromJSON(..), (.:), (.:?))
|
||||
import qualified Data.Aeson as A
|
||||
import qualified Data.ByteString.Lazy as LBS
|
||||
import System.Process (readProcessWithExitCode)
|
||||
import System.Exit (ExitCode(..))
|
||||
import Generated.Types
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Request / response types
|
||||
|
||||
data BridgeRequest = BridgeRequest
|
||||
{ provider :: !Text
|
||||
, model :: !Text
|
||||
, systemPrompt :: !(Maybe Text)
|
||||
, prompt :: !Text
|
||||
, maxTokens :: !Int
|
||||
, temperature :: !Double
|
||||
}
|
||||
|
||||
data BridgeResponse = BridgeResponse
|
||||
{ content :: !Text
|
||||
, modelUsed :: !Text
|
||||
, tokensIn :: !Int
|
||||
, tokensOut :: !Int
|
||||
, finishReason :: !Text
|
||||
} deriving (Show)
|
||||
|
||||
data BridgeError = BridgeError
|
||||
{ errorMessage :: !Text
|
||||
, errorType :: !Text
|
||||
} deriving (Show)
|
||||
|
||||
instance FromJSON BridgeResponse where
|
||||
parseJSON = A.withObject "BridgeResponse" \o -> BridgeResponse
|
||||
<$> o .: "content"
|
||||
<*> o .: "model"
|
||||
<*> o .: "tokensIn"
|
||||
<*> o .: "tokensOut"
|
||||
<*> o .: "finishReason"
|
||||
|
||||
instance FromJSON BridgeError where
|
||||
parseJSON = A.withObject "BridgeError" \o -> BridgeError
|
||||
<$> o .: "error"
|
||||
<*> o .: "errorType"
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Core bridge call
|
||||
|
||||
-- | Invoke the llm_bridge.py subprocess with the given request.
|
||||
callBridge :: BridgeRequest -> IO (Either BridgeError BridgeResponse)
|
||||
callBridge req = do
|
||||
let payload = LBS.toStrict . encode $ object
|
||||
[ "provider" .= req.provider
|
||||
, "model" .= req.model
|
||||
, "systemPrompt" .= req.systemPrompt
|
||||
, "prompt" .= req.prompt
|
||||
, "maxTokens" .= req.maxTokens
|
||||
, "temperature" .= req.temperature
|
||||
]
|
||||
(exitCode, stdout, stderr) <-
|
||||
readProcessWithExitCode "python3" ["scripts/llm_bridge.py"] (cs payload)
|
||||
let outBytes = LBS.fromStrict (cs stdout)
|
||||
case exitCode of
|
||||
ExitSuccess ->
|
||||
case decode outBytes of
|
||||
Just v -> pure (Right v)
|
||||
Nothing -> pure (Left (BridgeError "Unparseable bridge output" "ParseError"))
|
||||
ExitFailure _ ->
|
||||
case decode outBytes of
|
||||
Just v -> pure (Left v)
|
||||
Nothing -> pure (Left (BridgeError (cs stderr) "BridgeError"))
|
||||
|
||||
-- | Call the bridge using an AgentRegistration record.
|
||||
callAgent :: AgentRegistration -> Text -> IO (Either BridgeError BridgeResponse)
|
||||
callAgent agent userPrompt =
|
||||
callBridge BridgeRequest
|
||||
{ provider = agent.provider
|
||||
, model = agent.modelName
|
||||
, systemPrompt = agent.systemPrompt
|
||||
, prompt = userPrompt
|
||||
, maxTokens = 2000
|
||||
, temperature = 0.7
|
||||
}
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- AI governance policy check
|
||||
|
||||
-- | Returns True if the agent is allowed to perform the 'propose' action on
|
||||
-- the given artifact_type in this hub.
|
||||
-- When no policy exists the default is permissive (True).
|
||||
checkGovernancePolicy ::
|
||||
(?modelContext :: ModelContext) =>
|
||||
Id Hub -> Id AgentRegistration -> Text -> IO Bool
|
||||
checkGovernancePolicy hubId agentId artifactType = do
|
||||
mPolicy <- query @AiGovernancePolicy
|
||||
|> filterWhere (#hubId, hubId)
|
||||
|> filterWhere (#agentRegistrationId, agentId)
|
||||
|> filterWhere (#artifactType, artifactType)
|
||||
|> filterWhere (#isActive, True)
|
||||
|> fetchOneOrNothing
|
||||
case mPolicy of
|
||||
Nothing -> pure True
|
||||
Just p -> pure ("propose" `elem` jsonArrayTexts p.allowedActions)
|
||||
|
||||
-- | Extract Text values from a JSONB array.
|
||||
jsonArrayTexts :: Value -> [Text]
|
||||
jsonArrayTexts (A.Array vs) =
|
||||
[ t | A.String t <- toList vs ]
|
||||
jsonArrayTexts _ = []
|
||||
41
Application/Helper/ModelRouter.hs
Normal file
41
Application/Helper/ModelRouter.hs
Normal file
@@ -0,0 +1,41 @@
|
||||
module Application.Helper.ModelRouter where
|
||||
|
||||
-- IHF Phase 11 — Advanced AI Federation (IHUB-WP-0012 T04)
|
||||
-- Resolve the AgentRegistration to use for a hub + task type.
|
||||
|
||||
import IHP.Prelude
|
||||
import IHP.ControllerPrelude
|
||||
import Generated.Types
|
||||
import Database.PostgreSQL.Simple (Only(..))
|
||||
|
||||
-- | Resolve the highest-priority active AgentRegistration for the given hub
|
||||
-- and task type. Returns Nothing if no matching policy exists (callers should
|
||||
-- fall back gracefully or surface an error to the operator).
|
||||
resolveAgent ::
|
||||
(?modelContext :: ModelContext) =>
|
||||
Id Hub -> Text -> IO (Maybe AgentRegistration)
|
||||
resolveAgent hubId taskType = do
|
||||
rows <- sqlQuery
|
||||
"SELECT mrp.agent_registration_id \
|
||||
\ FROM model_routing_policies mrp \
|
||||
\ WHERE mrp.hub_id = ? AND mrp.task_type = ? AND mrp.is_active = TRUE \
|
||||
\ ORDER BY mrp.priority DESC \
|
||||
\ LIMIT 1"
|
||||
(hubId, taskType)
|
||||
case rows of
|
||||
[Only agentId] -> fetchOneOrNothing agentId
|
||||
_ -> pure Nothing
|
||||
|
||||
-- | Return all active AgentRegistrations for a hub + task_type ordered by
|
||||
-- priority (highest first). Used by CollectiveProposals to fan out.
|
||||
resolveAllAgents ::
|
||||
(?modelContext :: ModelContext) =>
|
||||
Id Hub -> Text -> IO [AgentRegistration]
|
||||
resolveAllAgents hubId taskType = do
|
||||
rows <- sqlQuery
|
||||
"SELECT mrp.agent_registration_id \
|
||||
\ FROM model_routing_policies mrp \
|
||||
\ WHERE mrp.hub_id = ? AND mrp.task_type = ? AND mrp.is_active = TRUE \
|
||||
\ ORDER BY mrp.priority DESC"
|
||||
(hubId, taskType)
|
||||
mapM (fetch . (\(Only i) -> i)) rows
|
||||
134
Application/Migration/1744156800-ihf-phase11-ai-federation.sql
Normal file
134
Application/Migration/1744156800-ihf-phase11-ai-federation.sql
Normal file
@@ -0,0 +1,134 @@
|
||||
-- IHF Phase 11 — Advanced AI Federation (IHUB-WP-0012)
|
||||
-- Migration timestamp: 1744156800
|
||||
|
||||
-- agent_registrations: named, versioned AI agents backed by llm-connect providers
|
||||
CREATE TABLE agent_registrations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
provider TEXT NOT NULL,
|
||||
model_name TEXT NOT NULL,
|
||||
trust_level TEXT NOT NULL DEFAULT 'advisory',
|
||||
capabilities JSONB NOT NULL DEFAULT '[]',
|
||||
system_prompt TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (trust_level IN ('advisory', 'elevated', 'autonomous'))
|
||||
);
|
||||
|
||||
CREATE INDEX agent_registrations_hub_id_idx ON agent_registrations (hub_id);
|
||||
CREATE INDEX agent_registrations_slug_idx ON agent_registrations (slug);
|
||||
CREATE INDEX agent_registrations_is_active_idx ON agent_registrations (is_active);
|
||||
|
||||
-- model_routing_policies: task_type → agent selection rules per hub
|
||||
CREATE TABLE model_routing_policies (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
task_type TEXT NOT NULL,
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
UNIQUE (hub_id, task_type, priority)
|
||||
);
|
||||
|
||||
CREATE INDEX model_routing_policies_hub_task_idx ON model_routing_policies (hub_id, task_type);
|
||||
|
||||
-- agent_delegations: auditable inter-agent subtask delegation records
|
||||
CREATE TABLE agent_delegations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
delegating_agent_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
receiving_agent_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
parent_proposal_id UUID REFERENCES agent_proposals(id),
|
||||
scope TEXT NOT NULL,
|
||||
token_budget INTEGER NOT NULL DEFAULT 1000,
|
||||
tokens_used INTEGER,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
result JSONB,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
completed_at TIMESTAMP WITH TIME ZONE,
|
||||
CHECK (status IN ('pending', 'completed', 'failed', 'cancelled'))
|
||||
);
|
||||
|
||||
CREATE INDEX agent_delegations_delegating_idx ON agent_delegations (delegating_agent_id);
|
||||
CREATE INDEX agent_delegations_receiving_idx ON agent_delegations (receiving_agent_id);
|
||||
CREATE INDEX agent_delegations_parent_proposal_idx ON agent_delegations (parent_proposal_id);
|
||||
|
||||
-- collective_proposals: multi-agent proposals with attribution
|
||||
CREATE TABLE collective_proposals (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
summary TEXT,
|
||||
task_type TEXT NOT NULL,
|
||||
consensus_status TEXT NOT NULL DEFAULT 'pending',
|
||||
final_content JSONB,
|
||||
source_widget_id UUID REFERENCES widgets(id),
|
||||
source_candidate_id UUID REFERENCES requirement_candidates(id),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (consensus_status IN ('pending', 'consensus', 'divergent'))
|
||||
);
|
||||
|
||||
CREATE INDEX collective_proposals_task_type_idx ON collective_proposals (task_type);
|
||||
CREATE INDEX collective_proposals_consensus_status_idx ON collective_proposals (consensus_status);
|
||||
|
||||
-- collective_proposal_contributions: per-agent contribution records
|
||||
CREATE TABLE collective_proposal_contributions (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
collective_proposal_id UUID NOT NULL REFERENCES collective_proposals(id),
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
content JSONB NOT NULL,
|
||||
tokens_in INTEGER,
|
||||
tokens_out INTEGER,
|
||||
model_used TEXT,
|
||||
contributed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX collective_proposal_contributions_proposal_idx ON collective_proposal_contributions (collective_proposal_id);
|
||||
CREATE INDEX collective_proposal_contributions_agent_idx ON collective_proposal_contributions (agent_registration_id);
|
||||
|
||||
-- ai_governance_policies: per-hub rules controlling agent scope
|
||||
CREATE TABLE ai_governance_policies (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
artifact_type TEXT NOT NULL,
|
||||
allowed_actions JSONB NOT NULL DEFAULT '["read"]',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX ai_governance_policies_hub_agent_idx ON ai_governance_policies (hub_id, agent_registration_id);
|
||||
CREATE INDEX ai_governance_policies_is_active_idx ON ai_governance_policies (is_active);
|
||||
|
||||
-- agent_performance_records: periodic snapshots of per-agent metrics
|
||||
CREATE TABLE agent_performance_records (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
period_start TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
period_end TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
proposals_generated INTEGER NOT NULL DEFAULT 0,
|
||||
proposals_accepted INTEGER NOT NULL DEFAULT 0,
|
||||
proposals_rejected INTEGER NOT NULL DEFAULT 0,
|
||||
proposals_revised INTEGER NOT NULL DEFAULT 0,
|
||||
mean_confidence DOUBLE PRECISION,
|
||||
calibration_score DOUBLE PRECISION,
|
||||
computed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX agent_performance_records_agent_idx ON agent_performance_records (agent_registration_id);
|
||||
CREATE INDEX agent_performance_records_period_idx ON agent_performance_records (period_start, period_end);
|
||||
|
||||
-- Extend agent_proposals with agent_registration_id and token tracking
|
||||
ALTER TABLE agent_proposals
|
||||
ADD COLUMN agent_registration_id UUID REFERENCES agent_registrations(id),
|
||||
ADD COLUMN tokens_in INTEGER,
|
||||
ADD COLUMN tokens_out INTEGER;
|
||||
|
||||
CREATE INDEX agent_proposals_agent_registration_idx ON agent_proposals (agent_registration_id);
|
||||
@@ -865,3 +865,143 @@ CREATE TABLE governance_template_clones (
|
||||
|
||||
CREATE INDEX governance_template_clones_template_idx ON governance_template_clones (governance_template_id);
|
||||
CREATE INDEX governance_template_clones_hub_idx ON governance_template_clones (cloning_hub_id);
|
||||
|
||||
-- IHF Phase 11 — Advanced AI Federation (IHUB-WP-0012)
|
||||
|
||||
-- agent_registrations: named, versioned AI agents backed by llm-connect providers
|
||||
-- GAAF: trust_level CHECK constraint — no bare TEXT discriminator
|
||||
CREATE TABLE agent_registrations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
provider TEXT NOT NULL,
|
||||
-- provider values: openrouter | gemini | openai | claude-code
|
||||
model_name TEXT NOT NULL,
|
||||
trust_level TEXT NOT NULL DEFAULT 'advisory',
|
||||
capabilities JSONB NOT NULL DEFAULT '[]',
|
||||
system_prompt TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (trust_level IN ('advisory', 'elevated', 'autonomous'))
|
||||
);
|
||||
|
||||
CREATE INDEX agent_registrations_hub_id_idx ON agent_registrations (hub_id);
|
||||
CREATE INDEX agent_registrations_slug_idx ON agent_registrations (slug);
|
||||
CREATE INDEX agent_registrations_is_active_idx ON agent_registrations (is_active);
|
||||
|
||||
-- model_routing_policies: task_type → agent selection rules per hub
|
||||
CREATE TABLE model_routing_policies (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
task_type TEXT NOT NULL,
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
UNIQUE (hub_id, task_type, priority)
|
||||
);
|
||||
|
||||
CREATE INDEX model_routing_policies_hub_task_idx ON model_routing_policies (hub_id, task_type);
|
||||
|
||||
-- agent_delegations: auditable inter-agent subtask delegation records
|
||||
-- GAAF: status CHECK constraint
|
||||
CREATE TABLE agent_delegations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
delegating_agent_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
receiving_agent_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
parent_proposal_id UUID REFERENCES agent_proposals(id),
|
||||
scope TEXT NOT NULL,
|
||||
token_budget INTEGER NOT NULL DEFAULT 1000,
|
||||
tokens_used INTEGER,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
result JSONB,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
completed_at TIMESTAMP WITH TIME ZONE,
|
||||
CHECK (status IN ('pending', 'completed', 'failed', 'cancelled'))
|
||||
);
|
||||
|
||||
CREATE INDEX agent_delegations_delegating_idx ON agent_delegations (delegating_agent_id);
|
||||
CREATE INDEX agent_delegations_receiving_idx ON agent_delegations (receiving_agent_id);
|
||||
CREATE INDEX agent_delegations_parent_proposal_idx ON agent_delegations (parent_proposal_id);
|
||||
|
||||
-- collective_proposals: multi-agent proposals with attribution
|
||||
-- GAAF: consensus_status CHECK constraint
|
||||
CREATE TABLE collective_proposals (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
summary TEXT,
|
||||
task_type TEXT NOT NULL,
|
||||
consensus_status TEXT NOT NULL DEFAULT 'pending',
|
||||
final_content JSONB,
|
||||
source_widget_id UUID REFERENCES widgets(id),
|
||||
source_candidate_id UUID REFERENCES requirement_candidates(id),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (consensus_status IN ('pending', 'consensus', 'divergent'))
|
||||
);
|
||||
|
||||
CREATE INDEX collective_proposals_task_type_idx ON collective_proposals (task_type);
|
||||
CREATE INDEX collective_proposals_consensus_status_idx ON collective_proposals (consensus_status);
|
||||
|
||||
-- collective_proposal_contributions: per-agent contribution records
|
||||
CREATE TABLE collective_proposal_contributions (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
collective_proposal_id UUID NOT NULL REFERENCES collective_proposals(id),
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
content JSONB NOT NULL,
|
||||
tokens_in INTEGER,
|
||||
tokens_out INTEGER,
|
||||
model_used TEXT,
|
||||
contributed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX collective_proposal_contributions_proposal_idx ON collective_proposal_contributions (collective_proposal_id);
|
||||
CREATE INDEX collective_proposal_contributions_agent_idx ON collective_proposal_contributions (agent_registration_id);
|
||||
|
||||
-- ai_governance_policies: per-hub rules controlling agent scope
|
||||
-- allowed_actions is JSONB array; elements validated at controller layer
|
||||
-- (each element: read | propose | delegate | auto_apply)
|
||||
CREATE TABLE ai_governance_policies (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
artifact_type TEXT NOT NULL,
|
||||
allowed_actions JSONB NOT NULL DEFAULT '["read"]',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX ai_governance_policies_hub_agent_idx ON ai_governance_policies (hub_id, agent_registration_id);
|
||||
CREATE INDEX ai_governance_policies_is_active_idx ON ai_governance_policies (is_active);
|
||||
|
||||
-- agent_performance_records: periodic snapshots of per-agent metrics
|
||||
CREATE TABLE agent_performance_records (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
period_start TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
period_end TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
proposals_generated INTEGER NOT NULL DEFAULT 0,
|
||||
proposals_accepted INTEGER NOT NULL DEFAULT 0,
|
||||
proposals_rejected INTEGER NOT NULL DEFAULT 0,
|
||||
proposals_revised INTEGER NOT NULL DEFAULT 0,
|
||||
mean_confidence DOUBLE PRECISION,
|
||||
calibration_score DOUBLE PRECISION,
|
||||
computed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX agent_performance_records_agent_idx ON agent_performance_records (agent_registration_id);
|
||||
CREATE INDEX agent_performance_records_period_idx ON agent_performance_records (period_start, period_end);
|
||||
|
||||
-- Extend agent_proposals with agent_registration_id and token tracking (Phase 11)
|
||||
ALTER TABLE agent_proposals
|
||||
ADD COLUMN agent_registration_id UUID REFERENCES agent_registrations(id),
|
||||
ADD COLUMN tokens_in INTEGER,
|
||||
ADD COLUMN tokens_out INTEGER;
|
||||
|
||||
CREATE INDEX agent_proposals_agent_registration_idx ON agent_proposals (agent_registration_id);
|
||||
|
||||
Reference in New Issue
Block a user