From 88a4f15ce1310f8ee8693835be14aa5280233f17 Mon Sep 17 00:00:00 2001 From: soryu Date: Thu, 5 Feb 2026 23:42:48 +0000 Subject: Add directive-first chain system redesign Redesigns the chain system with a directive-first architecture where Directive is the top-level entity (the "why/what") and Chains are generated execution plans (the "how") that can be dynamically modified. Backend: - Add database migration for directive system tables - Add Directive, DirectiveChain, ChainStep, DirectiveEvent models - Add DirectiveVerifier and DirectiveApproval models - Add orchestration module with engine, planner, and verifier - Add comprehensive API handlers for directives - Add daemon CLI commands for directive management - Add directive skill documentation - Integrate contract completion with directive engine - Add SSE endpoint for real-time directive events Frontend: - Add directives route with split-view layout - Add 6-tab detail view (Overview, Chain, Events, Evaluations, Approvals, Verifiers) - Add React Flow DAG visualization for chain steps - Add SSE subscription hook for real-time event updates - Add useDirectives and useDirectiveEventSubscription hooks - Add directive types and API functions Fixes: - Fix test failures in ws/protocol, task_output, completion_gate, patch - Fix word boundary matching in looks_like_task() - Fix parse_last() to find actual last completion gate - Fix create_export_patch when merge-base equals HEAD - Clean up clippy warnings in new code Co-Authored-By: Claude Opus 4.5 --- makima/src/daemon/api/directive.rs | 162 +++++++++++++++++++++++++++++++++++++ makima/src/daemon/api/mod.rs | 1 + 2 files changed, 163 insertions(+) create mode 100644 makima/src/daemon/api/directive.rs (limited to 'makima/src/daemon/api') diff --git a/makima/src/daemon/api/directive.rs b/makima/src/daemon/api/directive.rs new file mode 100644 index 0000000..5281d21 --- /dev/null +++ b/makima/src/daemon/api/directive.rs @@ -0,0 +1,162 @@ +//! Directive API methods. + +use uuid::Uuid; + +use super::client::{ApiClient, ApiError}; +use super::supervisor::JsonValue; + +impl ApiClient { + /// Create a new directive. + pub async fn create_directive( + &self, + goal: &str, + repository_url: Option<&str>, + autonomy_level: &str, + ) -> Result { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct CreateRequest<'a> { + goal: &'a str, + repository_url: Option<&'a str>, + autonomy_level: &'a str, + } + let req = CreateRequest { + goal, + repository_url, + autonomy_level, + }; + self.post("/api/v1/directives", &req).await + } + + /// List all directives for the authenticated user. + pub async fn list_directives( + &self, + status: Option<&str>, + limit: i32, + ) -> Result { + let mut params = Vec::new(); + if let Some(s) = status { + params.push(format!("status={}", s)); + } + params.push(format!("limit={}", limit)); + let query_string = format!("?{}", params.join("&")); + self.get(&format!("/api/v1/directives{}", query_string)) + .await + } + + /// Get a directive by ID (includes progress info). + pub async fn get_directive(&self, directive_id: Uuid) -> Result { + self.get(&format!("/api/v1/directives/{}", directive_id)) + .await + } + + /// Archive a directive. + pub async fn archive_directive(&self, directive_id: Uuid) -> Result { + self.delete_with_response(&format!("/api/v1/directives/{}", directive_id)) + .await + } + + /// Start a directive (plans and begins execution). + pub async fn start_directive(&self, directive_id: Uuid) -> Result { + self.post_empty(&format!("/api/v1/directives/{}/start", directive_id)) + .await + } + + /// Pause a directive. + pub async fn pause_directive(&self, directive_id: Uuid) -> Result { + self.post_empty(&format!("/api/v1/directives/{}/pause", directive_id)) + .await + } + + /// Resume a paused directive. + pub async fn resume_directive(&self, directive_id: Uuid) -> Result { + self.post_empty(&format!("/api/v1/directives/{}/resume", directive_id)) + .await + } + + /// Stop a directive. + pub async fn stop_directive(&self, directive_id: Uuid) -> Result { + self.post_empty(&format!("/api/v1/directives/{}/stop", directive_id)) + .await + } + + /// Get the current chain and steps for a directive. + pub async fn get_directive_chain(&self, directive_id: Uuid) -> Result { + self.get(&format!("/api/v1/directives/{}/chain", directive_id)) + .await + } + + /// Get directive DAG structure for visualization. + pub async fn get_directive_graph(&self, directive_id: Uuid) -> Result { + self.get(&format!("/api/v1/directives/{}/chain/graph", directive_id)) + .await + } + + /// List events for a directive. + pub async fn list_directive_events( + &self, + directive_id: Uuid, + limit: i32, + ) -> Result { + self.get(&format!( + "/api/v1/directives/{}/events?limit={}", + directive_id, limit + )) + .await + } + + /// List pending approvals for a directive. + pub async fn list_directive_approvals( + &self, + directive_id: Uuid, + ) -> Result { + self.get(&format!("/api/v1/directives/{}/approvals", directive_id)) + .await + } + + /// Approve an approval request. + pub async fn approve_directive_request( + &self, + directive_id: Uuid, + approval_id: Uuid, + response: Option<&str>, + ) -> Result { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct ApprovalRequest<'a> { + response: Option<&'a str>, + } + let req = ApprovalRequest { response }; + self.post( + &format!( + "/api/v1/directives/{}/approvals/{}/approve", + directive_id, approval_id + ), + &req, + ) + .await + } + + /// Deny an approval request. + pub async fn deny_directive_request( + &self, + directive_id: Uuid, + approval_id: Uuid, + response: Option<&str>, + ) -> Result { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct ApprovalRequest<'a> { + response: Option<&'a str>, + } + let req = ApprovalRequest { response }; + self.post( + &format!( + "/api/v1/directives/{}/approvals/{}/deny", + directive_id, approval_id + ), + &req, + ) + .await + } +} diff --git a/makima/src/daemon/api/mod.rs b/makima/src/daemon/api/mod.rs index 7868907..f1f52d0 100644 --- a/makima/src/daemon/api/mod.rs +++ b/makima/src/daemon/api/mod.rs @@ -3,6 +3,7 @@ pub mod chain; pub mod client; pub mod contract; +pub mod directive; pub mod supervisor; pub use client::ApiClient; -- cgit v1.2.3