summaryrefslogtreecommitdiff
path: root/makima/src/db
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-02 02:34:50 +0000
committersoryu <soryu@soryu.co>2026-02-02 02:34:50 +0000
commit151e9d87e117b7980e6aad522ac8f3633eeca87a (patch)
treee80fb4301361b3b12e5abf8e442603db2d0622dc /makima/src/db
parenta2c147ddd59f55a07b5be0c8970169726b55c876 (diff)
downloadsoryu-151e9d87e117b7980e6aad522ac8f3633eeca87a.tar.gz
soryu-151e9d87e117b7980e6aad522ac8f3633eeca87a.zip
Make makima more opinionated and structured
Diffstat (limited to 'makima/src/db')
-rw-r--r--makima/src/db/models.rs94
-rw-r--r--makima/src/db/repository.rs131
2 files changed, 16 insertions, 209 deletions
diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs
index abdcce6..cef0a22 100644
--- a/makima/src/db/models.rs
+++ b/makima/src/db/models.rs
@@ -440,11 +440,6 @@ pub struct Task {
/// True for contract supervisor tasks. Only supervisors can spawn new tasks.
#[serde(default)]
pub is_supervisor: bool,
- /// Whether this is a red team monitoring task.
- /// Red team tasks monitor work task outputs and can notify
- /// the supervisor about potential issues.
- #[serde(default)]
- pub is_red_team: bool,
// Daemon/container info
pub daemon_id: Option<Uuid>,
@@ -575,9 +570,6 @@ pub struct TaskSummary {
/// True for contract supervisor tasks
#[serde(default)]
pub is_supervisor: bool,
- /// True for red team tasks that monitor and review other tasks' work
- #[serde(default)]
- pub is_red_team: bool,
/// Whether this task is hidden from the UI (user dismissed it)
#[serde(default)]
pub hidden: bool,
@@ -603,7 +595,6 @@ impl From<Task> for TaskSummary {
subtask_count: 0, // Would need separate query
version: task.version,
is_supervisor: task.is_supervisor,
- is_red_team: task.is_red_team,
hidden: task.hidden,
created_at: task.created_at,
updated_at: task.updated_at,
@@ -636,9 +627,6 @@ pub struct CreateTaskRequest {
/// True for contract supervisor tasks. Only supervisors can spawn new tasks.
#[serde(default)]
pub is_supervisor: bool,
- /// True for red team tasks that monitor and review other tasks' work.
- #[serde(default)]
- pub is_red_team: bool,
/// Priority (higher = more urgent)
#[serde(default)]
pub priority: i32,
@@ -1453,15 +1441,6 @@ pub struct Contract {
/// automatically merged to the master/main branch locally (without pushing or creating PRs).
#[serde(default)]
pub auto_merge_local: bool,
- /// Whether to spawn a red team task to monitor work tasks.
- /// When enabled, a parallel task monitors outputs and can alert
- /// the supervisor about potential issues.
- #[serde(default)]
- pub red_team_enabled: bool,
- /// Optional custom prompt/criteria for the red team to use
- /// when evaluating task outputs.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub red_team_prompt: Option<String>,
/// Phase configuration copied from template at contract creation (raw JSON).
/// When present, this overrides the built-in contract type phases.
/// Use `get_phase_config()` to get the parsed PhaseConfig.
@@ -1649,9 +1628,6 @@ pub struct ContractSummary {
/// When true with local_only, automatically merge completed tasks to target branch locally.
#[serde(default)]
pub auto_merge_local: bool,
- /// Whether red team monitoring is enabled for this contract.
- #[serde(default)]
- pub red_team_enabled: bool,
pub file_count: i64,
pub task_count: i64,
pub repository_count: i64,
@@ -1723,15 +1699,6 @@ pub struct CreateContractRequest {
/// automatically merged to the master/main branch locally (without pushing or creating PRs).
#[serde(default)]
pub auto_merge_local: Option<bool>,
- /// Enable red team monitoring for this contract.
- /// When enabled, a parallel task monitors work task outputs
- /// and can alert the supervisor about potential issues.
- #[serde(default)]
- pub red_team_enabled: Option<bool>,
- /// Optional custom criteria for the red team to evaluate.
- /// Examples: "Focus on security vulnerabilities",
- /// "Ensure all functions have tests", etc.
- pub red_team_prompt: Option<String>,
}
/// Request payload for updating a contract
@@ -2542,67 +2509,6 @@ pub struct SupervisorHeartbeatRequest {
pub pending_task_ids: Vec<Uuid>,
}
-// =============================================================================
-// Red Team Types
-// =============================================================================
-
-/// Red Team notification record
-#[derive(Debug, Clone, FromRow, Serialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct RedTeamNotification {
- pub id: Uuid,
- pub contract_id: Uuid,
- pub red_team_task_id: Uuid,
- pub related_task_id: Option<Uuid>,
-
- pub message: String,
- pub severity: String,
- pub file_path: Option<String>,
- pub context: Option<String>,
-
- pub delivered: bool,
- pub delivered_at: Option<DateTime<Utc>>,
- pub acknowledged: bool,
- pub acknowledged_at: Option<DateTime<Utc>>,
-
- pub created_at: DateTime<Utc>,
-}
-
-/// Severity levels for red team notifications
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
-#[serde(rename_all = "lowercase")]
-pub enum NotificationSeverity {
- Low,
- Medium,
- High,
- Critical,
-}
-
-impl std::fmt::Display for NotificationSeverity {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::Low => write!(f, "low"),
- Self::Medium => write!(f, "medium"),
- Self::High => write!(f, "high"),
- Self::Critical => write!(f, "critical"),
- }
- }
-}
-
-impl std::str::FromStr for NotificationSeverity {
- type Err = String;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s.to_lowercase().as_str() {
- "low" => Ok(Self::Low),
- "medium" => Ok(Self::Medium),
- "high" => Ok(Self::High),
- "critical" => Ok(Self::Critical),
- _ => Err(format!("Invalid severity: {}", s)),
- }
- }
-}
-
// ============================================================================
// Supervisor Status API Types
// ============================================================================
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs
index e308df7..2ecbc4a 100644
--- a/makima/src/db/repository.rs
+++ b/makima/src/db/repository.rs
@@ -12,7 +12,7 @@ use super::models::{
CreateFileRequest, CreateTaskRequest, CreateTemplateRequest, Daemon, DaemonTaskAssignment,
DaemonWithCapacity, DeliverableDefinition, File, FileSummary, FileVersion, HistoryEvent,
HistoryQueryFilters, MeshChatConversation, MeshChatMessageRecord, PhaseChangeResult,
- PhaseConfig, PhaseDefinition, RedTeamNotification, SupervisorHeartbeatRecord, SupervisorState,
+ PhaseConfig, PhaseDefinition, SupervisorHeartbeatRecord, SupervisorState,
Task, TaskCheckpoint, TaskEvent, TaskSummary, UpdateContractRequest, UpdateFileRequest,
UpdateTaskRequest, UpdateTemplateRequest,
};
@@ -691,11 +691,11 @@ pub async fn create_task(pool: &PgPool, req: CreateTaskRequest) -> Result<Task,
r#"
INSERT INTO tasks (
contract_id, parent_task_id, depth, name, description, plan, priority,
- is_supervisor, is_red_team, repository_url, base_branch, target_branch, merge_mode,
+ is_supervisor, repository_url, base_branch, target_branch, merge_mode,
target_repo_path, completion_action, continue_from_task_id, copy_files,
branched_from_task_id, conversation_state, supervisor_worktree_task_id
)
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
RETURNING *
"#,
)
@@ -707,7 +707,6 @@ pub async fn create_task(pool: &PgPool, req: CreateTaskRequest) -> Result<Task,
.bind(&req.plan)
.bind(req.priority)
.bind(req.is_supervisor)
- .bind(req.is_red_team)
.bind(&repo_url)
.bind(&base_branch)
.bind(&target_branch)
@@ -748,8 +747,7 @@ pub async fn list_tasks(pool: &PgPool) -> Result<Vec<TaskSummary>, sqlx::Error>
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, COALESCE(t.is_red_team, false) as is_red_team,
- COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.parent_task_id IS NULL AND COALESCE(t.hidden, false) = false
@@ -770,8 +768,7 @@ pub async fn list_subtasks(pool: &PgPool, parent_id: Uuid) -> Result<Vec<TaskSum
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, COALESCE(t.is_red_team, false) as is_red_team,
- COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.parent_task_id = $1
@@ -1106,11 +1103,11 @@ pub async fn create_task_for_owner(
r#"
INSERT INTO tasks (
owner_id, contract_id, parent_task_id, depth, name, description, plan, priority,
- is_supervisor, is_red_team, repository_url, base_branch, target_branch, merge_mode,
+ is_supervisor, repository_url, base_branch, target_branch, merge_mode,
target_repo_path, completion_action, continue_from_task_id, copy_files,
branched_from_task_id, conversation_state, supervisor_worktree_task_id
)
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)
RETURNING *
"#,
)
@@ -1123,7 +1120,6 @@ pub async fn create_task_for_owner(
.bind(&req.plan)
.bind(req.priority)
.bind(req.is_supervisor)
- .bind(req.is_red_team)
.bind(&repo_url)
.bind(&base_branch)
.bind(&target_branch)
@@ -1172,8 +1168,7 @@ pub async fn list_tasks_for_owner(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, COALESCE(t.is_red_team, false) as is_red_team,
- COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.owner_id = $1 AND t.parent_task_id IS NULL AND COALESCE(t.hidden, false) = false
@@ -1199,8 +1194,7 @@ pub async fn list_subtasks_for_owner(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, COALESCE(t.is_red_team, false) as is_red_team,
- COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.owner_id = $1 AND t.parent_task_id = $2
@@ -1721,8 +1715,7 @@ pub async fn list_sibling_tasks(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, COALESCE(t.is_red_team, false) as is_red_team,
- COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.parent_task_id = $1 AND t.id != $2
@@ -1744,8 +1737,7 @@ pub async fn list_sibling_tasks(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, COALESCE(t.is_red_team, false) as is_red_team,
- COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.parent_task_id IS NULL AND t.id != $1
@@ -2467,15 +2459,14 @@ pub async fn create_contract_for_owner(
let phase_guard = req.phase_guard.unwrap_or(false);
let local_only = req.local_only.unwrap_or(false);
let auto_merge_local = req.auto_merge_local.unwrap_or(false);
- let red_team_enabled = req.red_team_enabled.unwrap_or(false);
// Serialize phase_config to JSON
let phase_config_json = serde_json::to_value(&phase_config).ok();
sqlx::query_as::<_, Contract>(
r#"
- INSERT INTO contracts (owner_id, name, description, contract_type, phase, autonomous_loop, phase_guard, local_only, auto_merge_local, red_team_enabled, red_team_prompt, phase_config)
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
+ INSERT INTO contracts (owner_id, name, description, contract_type, phase, autonomous_loop, phase_guard, local_only, auto_merge_local, phase_config)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING *
"#,
)
@@ -2488,8 +2479,6 @@ pub async fn create_contract_for_owner(
.bind(phase_guard)
.bind(local_only)
.bind(auto_merge_local)
- .bind(red_team_enabled)
- .bind(&req.red_team_prompt)
.bind(phase_config_json)
.fetch_one(pool)
.await
@@ -2523,7 +2512,7 @@ pub async fn list_contracts_for_owner(
r#"
SELECT
c.id, c.name, c.description, c.contract_type, c.phase, c.status,
- c.supervisor_task_id, c.local_only, c.auto_merge_local, c.red_team_enabled, c.version, c.created_at,
+ c.supervisor_task_id, c.local_only, c.auto_merge_local, c.version, c.created_at,
(SELECT COUNT(*) FROM files WHERE contract_id = c.id) as file_count,
(SELECT COUNT(*) FROM tasks WHERE contract_id = c.id) as task_count,
(SELECT COUNT(*) FROM contract_repositories WHERE contract_id = c.id) as repository_count
@@ -2547,7 +2536,7 @@ pub async fn get_contract_summary_for_owner(
r#"
SELECT
c.id, c.name, c.description, c.contract_type, c.phase, c.status,
- c.supervisor_task_id, c.local_only, c.auto_merge_local, c.red_team_enabled, c.version, c.created_at,
+ c.supervisor_task_id, c.local_only, c.auto_merge_local, c.version, c.created_at,
(SELECT COUNT(*) FROM files WHERE contract_id = c.id) as file_count,
(SELECT COUNT(*) FROM tasks WHERE contract_id = c.id) as task_count,
(SELECT COUNT(*) FROM contract_repositories WHERE contract_id = c.id) as repository_count
@@ -3118,8 +3107,7 @@ pub async fn list_tasks_in_contract(
t.parent_task_id, t.depth, t.name, t.status, t.priority,
t.progress_summary,
(SELECT COUNT(*) FROM tasks WHERE parent_task_id = t.id) as subtask_count,
- t.version, t.is_supervisor, COALESCE(t.is_red_team, false) as is_red_team,
- COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
+ t.version, t.is_supervisor, COALESCE(t.hidden, false) as hidden, t.created_at, t.updated_at
FROM tasks t
LEFT JOIN contracts c ON t.contract_id = c.id
WHERE t.contract_id = $1 AND t.owner_id = $2
@@ -4774,93 +4762,6 @@ pub async fn delete_checkpoint_patches_for_task(
// =============================================================================
// Red Team Notifications
// =============================================================================
-
-/// Create a red team notification.
-/// Red team tasks use this to report issues found during implementation review.
-pub async fn create_red_team_notification(
- pool: &PgPool,
- contract_id: Uuid,
- red_team_task_id: Uuid,
- message: &str,
- severity: &str,
- related_task_id: Option<Uuid>,
- file_path: Option<&str>,
- context: Option<&str>,
-) -> Result<RedTeamNotification, RepositoryError> {
- sqlx::query_as::<_, RedTeamNotification>(
- r#"
- INSERT INTO red_team_notifications
- (contract_id, red_team_task_id, related_task_id, message, severity, file_path, context)
- VALUES ($1, $2, $3, $4, $5, $6, $7)
- RETURNING *
- "#,
- )
- .bind(contract_id)
- .bind(red_team_task_id)
- .bind(related_task_id)
- .bind(message)
- .bind(severity)
- .bind(file_path)
- .bind(context)
- .fetch_one(pool)
- .await
- .map_err(RepositoryError::Database)
-}
-
-/// Mark a notification as delivered to the supervisor.
-pub async fn mark_notification_delivered(
- pool: &PgPool,
- notification_id: Uuid,
-) -> Result<RedTeamNotification, RepositoryError> {
- sqlx::query_as::<_, RedTeamNotification>(
- r#"
- UPDATE red_team_notifications
- SET delivered = TRUE, delivered_at = NOW()
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(notification_id)
- .fetch_one(pool)
- .await
- .map_err(RepositoryError::Database)
-}
-
-/// Get the red team task for a contract (if one exists).
-/// Returns the most recently created red team task for the contract.
-pub async fn get_red_team_task_for_contract(
- pool: &PgPool,
- contract_id: Uuid,
-) -> Result<Option<Task>, RepositoryError> {
- sqlx::query_as::<_, Task>(
- r#"
- SELECT * FROM tasks
- WHERE contract_id = $1 AND is_red_team = TRUE
- ORDER BY created_at DESC
- LIMIT 1
- "#,
- )
- .bind(contract_id)
- .fetch_optional(pool)
- .await
- .map_err(RepositoryError::Database)
-}
-
-/// Get the count of notifications for a red team task.
-pub async fn get_notification_count_for_task(
- pool: &PgPool,
- red_team_task_id: Uuid,
-) -> Result<i64, RepositoryError> {
- let result: (i64,) = sqlx::query_as(
- "SELECT COUNT(*) FROM red_team_notifications WHERE red_team_task_id = $1",
- )
- .bind(red_team_task_id)
- .fetch_one(pool)
- .await
- .map_err(RepositoryError::Database)?;
- Ok(result.0)
-}
-
// =============================================================================
// Supervisor Status API Helpers
// =============================================================================