diff options
Diffstat (limited to 'makima/src/db/repository.rs')
| -rw-r--r-- | makima/src/db/repository.rs | 74 |
1 files changed, 68 insertions, 6 deletions
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index 1021c35..27bd47e 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -5625,12 +5625,15 @@ pub async fn check_directive_idle( } /// Update a directive's goal and bump goal_updated_at. -/// Reactivates draft/idle/paused directives and clears any stale orchestrator -/// task so that planning/replanning triggers on the next reconciler tick. +/// Reactivates draft/idle/paused/inactive directives and clears any stale +/// orchestrator task so that planning/replanning triggers on the next +/// reconciler tick. /// -/// `draft` is included in the flip set because the document-mode UI treats -/// the first goal save as the implicit "start" — without this, a brand-new -/// directive's goal save would persist but never spawn a planner. +/// `draft` flips because the document-mode UI treats the first goal save as +/// the implicit "start". `inactive` flips because editing a contract whose +/// last revision was already shipped is the way the user kicks off an +/// amendment — the planner picks it up via phase_planning/replanning and +/// uses get_latest_merged_revision to learn the BEFORE→AFTER diff. pub async fn update_directive_goal( pool: &PgPool, owner_id: Uuid, @@ -5642,7 +5645,10 @@ pub async fn update_directive_goal( UPDATE directives SET goal = $3, goal_updated_at = NOW(), - status = CASE WHEN status IN ('draft', 'idle', 'paused') THEN 'active' ELSE status END, + status = CASE + WHEN status IN ('draft', 'idle', 'paused', 'inactive') THEN 'active' + ELSE status + END, orchestrator_task_id = NULL, updated_at = NOW(), version = version + 1 @@ -5657,6 +5663,62 @@ pub async fn update_directive_goal( .await } +/// Mark a directive 'inactive'. Used at the moment a PR is raised — at that +/// point the contract's current iteration is "shipped" and editing the goal +/// (Stage 4) starts an amendment cycle. Idempotent: no-op if status is +/// already inactive or already past it (e.g. archived). +pub async fn set_directive_inactive( + pool: &PgPool, + directive_id: Uuid, +) -> Result<(), sqlx::Error> { + sqlx::query( + r#" + UPDATE directives + SET status = 'inactive', + updated_at = NOW(), + version = version + 1 + WHERE id = $1 + AND status IN ('active', 'idle', 'paused') + "#, + ) + .bind(directive_id) + .execute(pool) + .await?; + Ok(()) +} + +/// Reset a directive for a "new draft" cycle: clear the goal back to empty, +/// flip status to 'draft', and detach the current pr_url / pr_branch / +/// orchestrator linkage so the next goal save starts fresh. Prior revisions +/// remain in `directive_revisions` as the historical record. Used by the +/// sidebar's "New draft" right-click on inactive contracts. +pub async fn reset_directive_for_new_draft( + pool: &PgPool, + owner_id: Uuid, + directive_id: Uuid, +) -> Result<Option<Directive>, sqlx::Error> { + sqlx::query_as::<_, Directive>( + r#" + UPDATE directives + SET goal = '', + goal_updated_at = NOW(), + status = 'draft', + pr_url = NULL, + pr_branch = NULL, + orchestrator_task_id = NULL, + completion_task_id = NULL, + updated_at = NOW(), + version = version + 1 + WHERE id = $1 AND owner_id = $2 + RETURNING * + "#, + ) + .bind(directive_id) + .bind(owner_id) + .fetch_optional(pool) + .await +} + /// Update a directive's goal WITHOUT clearing the orchestrator task id. /// /// This is the path used by the goal-edit interrupt cycle: when a small goal |
