summaryrefslogtreecommitdiff
path: root/makima/src/db
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/db')
-rw-r--r--makima/src/db/models.rs7
-rw-r--r--makima/src/db/repository.rs123
2 files changed, 128 insertions, 2 deletions
diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs
index 9159fd5..542339f 100644
--- a/makima/src/db/models.rs
+++ b/makima/src/db/models.rs
@@ -2711,6 +2711,9 @@ pub struct Directive {
pub local_path: Option<String>,
pub base_branch: Option<String>,
pub orchestrator_task_id: Option<Uuid>,
+ pub pr_url: Option<String>,
+ pub pr_branch: Option<String>,
+ pub completion_task_id: Option<Uuid>,
pub goal_updated_at: DateTime<Utc>,
pub started_at: Option<DateTime<Utc>>,
pub version: i32,
@@ -2758,6 +2761,8 @@ pub struct DirectiveSummary {
pub status: String,
pub repository_url: Option<String>,
pub orchestrator_task_id: Option<Uuid>,
+ pub pr_url: Option<String>,
+ pub completion_task_id: Option<Uuid>,
pub version: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
@@ -2797,6 +2802,8 @@ pub struct UpdateDirectiveRequest {
pub local_path: Option<String>,
pub base_branch: Option<String>,
pub orchestrator_task_id: Option<Uuid>,
+ pub pr_url: Option<String>,
+ pub pr_branch: Option<String>,
pub version: Option<i32>,
}
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs
index 323e74e..358ab48 100644
--- a/makima/src/db/repository.rs
+++ b/makima/src/db/repository.rs
@@ -4991,7 +4991,8 @@ pub async fn list_directives_for_owner(
r#"
SELECT
d.id, d.owner_id, d.title, d.goal, d.status, d.repository_url,
- d.orchestrator_task_id, d.version, d.created_at, d.updated_at,
+ d.orchestrator_task_id, d.pr_url, d.completion_task_id,
+ d.version, d.created_at, d.updated_at,
COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id), 0) as total_steps,
COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id AND status = 'completed'), 0) as completed_steps,
COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id AND status = 'running'), 0) as running_steps,
@@ -5043,12 +5044,15 @@ pub async fn update_directive_for_owner(
let local_path = req.local_path.as_deref().or(current.local_path.as_deref());
let base_branch = req.base_branch.as_deref().or(current.base_branch.as_deref());
let orchestrator_task_id = req.orchestrator_task_id.or(current.orchestrator_task_id);
+ let pr_url = req.pr_url.as_deref().or(current.pr_url.as_deref());
+ let pr_branch = req.pr_branch.as_deref().or(current.pr_branch.as_deref());
let result = sqlx::query_as::<_, Directive>(
r#"
UPDATE directives
SET title = $3, goal = $4, status = $5, repository_url = $6, local_path = $7,
- base_branch = $8, orchestrator_task_id = $9, version = version + 1, updated_at = NOW()
+ base_branch = $8, orchestrator_task_id = $9, pr_url = $10, pr_branch = $11,
+ version = version + 1, updated_at = NOW()
WHERE id = $1 AND owner_id = $2
RETURNING *
"#,
@@ -5062,6 +5066,8 @@ pub async fn update_directive_for_owner(
.bind(local_path)
.bind(base_branch)
.bind(orchestrator_task_id)
+ .bind(pr_url)
+ .bind(pr_branch)
.fetch_optional(pool)
.await
.map_err(RepositoryError::Database)?;
@@ -5096,6 +5102,119 @@ pub async fn delete_directive_for_owner(
}
// =============================================================================
+// Directive Completion Helpers
+// =============================================================================
+
+/// Row type for completed step tasks.
+#[derive(Debug, Clone, sqlx::FromRow)]
+pub struct CompletedStepTask {
+ pub step_name: String,
+ pub task_id: Uuid,
+ pub task_name: String,
+}
+
+/// Row type for directive completion task status check.
+#[derive(Debug, Clone, sqlx::FromRow)]
+pub struct DirectiveCompletionCheck {
+ pub directive_id: Uuid,
+ pub completion_task_id: Uuid,
+ pub task_status: String,
+ pub pr_url: Option<String>,
+}
+
+/// Get idle directives that need a completion task spawned.
+/// Conditions: status = 'idle', no completion_task_id, has repository_url,
+/// and has at least one completed step with a task_id.
+pub async fn get_idle_directives_needing_completion(
+ pool: &PgPool,
+) -> Result<Vec<Directive>, sqlx::Error> {
+ sqlx::query_as::<_, Directive>(
+ r#"
+ SELECT d.*
+ FROM directives d
+ WHERE d.status = 'idle'
+ AND d.completion_task_id IS NULL
+ AND d.repository_url IS NOT NULL
+ AND EXISTS (
+ SELECT 1 FROM directive_steps ds
+ WHERE ds.directive_id = d.id
+ AND ds.status = 'completed'
+ AND ds.task_id IS NOT NULL
+ )
+ "#,
+ )
+ .fetch_all(pool)
+ .await
+}
+
+/// Get directives with active completion tasks, joined with task status.
+pub async fn get_completion_tasks_to_check(
+ pool: &PgPool,
+) -> Result<Vec<DirectiveCompletionCheck>, sqlx::Error> {
+ sqlx::query_as::<_, DirectiveCompletionCheck>(
+ r#"
+ SELECT d.id as directive_id, d.completion_task_id, t.status as task_status, d.pr_url
+ FROM directives d
+ JOIN tasks t ON t.id = d.completion_task_id
+ WHERE d.completion_task_id IS NOT NULL
+ "#,
+ )
+ .fetch_all(pool)
+ .await
+}
+
+/// Assign a completion task to a directive.
+pub async fn assign_completion_task(
+ pool: &PgPool,
+ directive_id: Uuid,
+ task_id: Uuid,
+) -> Result<(), sqlx::Error> {
+ sqlx::query(
+ r#"UPDATE directives SET completion_task_id = $2, updated_at = NOW() WHERE id = $1"#,
+ )
+ .bind(directive_id)
+ .bind(task_id)
+ .execute(pool)
+ .await?;
+ Ok(())
+}
+
+/// Clear the completion task from a directive.
+pub async fn clear_completion_task(
+ pool: &PgPool,
+ directive_id: Uuid,
+) -> Result<(), sqlx::Error> {
+ sqlx::query(
+ r#"UPDATE directives SET completion_task_id = NULL, updated_at = NOW() WHERE id = $1"#,
+ )
+ .bind(directive_id)
+ .execute(pool)
+ .await?;
+ Ok(())
+}
+
+/// Get completed step tasks for a directive (steps that have completed with an assigned task).
+pub async fn get_completed_step_tasks(
+ pool: &PgPool,
+ directive_id: Uuid,
+) -> Result<Vec<CompletedStepTask>, sqlx::Error> {
+ sqlx::query_as::<_, CompletedStepTask>(
+ r#"
+ SELECT ds.name as step_name, ds.task_id, t.name as task_name
+ FROM directive_steps ds
+ JOIN tasks t ON t.id = ds.task_id
+ WHERE ds.directive_id = $1
+ AND ds.status = 'completed'
+ AND ds.task_id IS NOT NULL
+ ORDER BY ds.order_index, ds.created_at
+ "#,
+ )
+ .bind(directive_id)
+ .fetch_all(pool)
+ .await
+}
+
+// =============================================================================
// Directive Step CRUD
// =============================================================================