summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-14 21:27:57 +0000
committersoryu <soryu@soryu.co>2026-02-14 21:27:57 +0000
commit3002fdeb91ad62e48bf0ad2bd5f1206acfc9539d (patch)
treeef8bed9718c39041191b58a284ee31f5d8d32521
parentafd820f99056caeada04c19d7c33fef615a809b4 (diff)
parent1f0dd5872bafd3776108edadcb519ae5de801e77 (diff)
downloadsoryu-3002fdeb91ad62e48bf0ad2bd5f1206acfc9539d.tar.gz
soryu-3002fdeb91ad62e48bf0ad2bd5f1206acfc9539d.zip
Merge remote-tracking branch 'origin/makima/soryu-co-soryu---makima--fix-directive-pr-creation-00fea7d9' into makima/directive-soryu-co-soryu-makima-c29f9112makima/soryu-co-soryu---makima--create-pr-for-all-directi-dae80fbbmakima/directive-soryu-co-soryu-makima-c29f9112
-rw-r--r--makima/src/daemon/skills/directive.md6
-rw-r--r--makima/src/db/repository.rs3
-rw-r--r--makima/src/orchestration/directive.rs78
3 files changed, 84 insertions, 3 deletions
diff --git a/makima/src/daemon/skills/directive.md b/makima/src/daemon/skills/directive.md
index 68d9277..9d2b644 100644
--- a/makima/src/daemon/skills/directive.md
+++ b/makima/src/daemon/skills/directive.md
@@ -76,6 +76,12 @@ Updates the goal and bumps `goalUpdatedAt`. If the directive is `idle`, it react
makima directive pause
```
+### Update Directive Metadata
+```bash
+makima directive update --pr-url "<url>" --pr-branch "<branch>"
+```
+Updates the directive's PR URL and/or PR branch. Used by completion tasks to store the PR URL after creating it.
+
## Memory Commands
Directives have an optional key-value memory system that persists across steps and planning cycles. Use memory to share context, decisions, and learned information between steps — so downstream tasks don't need to re-discover what earlier steps already figured out.
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs
index a2489aa..ed4a1fa 100644
--- a/makima/src/db/repository.rs
+++ b/makima/src/db/repository.rs
@@ -5194,6 +5194,7 @@ pub struct CompletedStepTask {
#[derive(Debug, Clone, sqlx::FromRow)]
pub struct DirectiveCompletionCheck {
pub directive_id: Uuid,
+ pub owner_id: Uuid,
pub completion_task_id: Uuid,
pub task_status: String,
pub pr_url: Option<String>,
@@ -5230,7 +5231,7 @@ pub async fn get_completion_tasks_to_check(
) -> 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
+ SELECT d.id as directive_id, d.owner_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
diff --git a/makima/src/orchestration/directive.rs b/makima/src/orchestration/directive.rs
index 6d5d63d..0deacca 100644
--- a/makima/src/orchestration/directive.rs
+++ b/makima/src/orchestration/directive.rs
@@ -637,6 +637,45 @@ impl DirectiveOrchestrator {
task_id = %check.completion_task_id,
"Completion task finished"
);
+
+ // If directive has no pr_url yet, try to extract from task output
+ if check.pr_url.is_none() {
+ match self.extract_pr_url_from_task(check.completion_task_id).await {
+ Ok(Some(url)) => {
+ tracing::info!(
+ directive_id = %check.directive_id,
+ pr_url = %url,
+ "Extracted PR URL from completion task output"
+ );
+ let update = crate::db::models::UpdateDirectiveRequest {
+ pr_url: Some(url),
+ ..Default::default()
+ };
+ let _ = repository::update_directive_for_owner(
+ &self.pool,
+ check.owner_id,
+ check.directive_id,
+ update,
+ )
+ .await;
+ }
+ Ok(None) => {
+ tracing::warn!(
+ directive_id = %check.directive_id,
+ task_id = %check.completion_task_id,
+ "Completion task finished but no PR URL found in output"
+ );
+ }
+ Err(e) => {
+ tracing::warn!(
+ directive_id = %check.directive_id,
+ error = %e,
+ "Failed to extract PR URL from completion task output"
+ );
+ }
+ }
+ }
+
repository::clear_completion_task(&self.pool, check.directive_id).await?;
}
"failed" | "interrupted" => {
@@ -698,6 +737,36 @@ impl DirectiveOrchestrator {
Ok(task.id)
}
+
+ /// Extract a GitHub PR URL from a completion task's output events.
+ /// Searches task output for patterns like `https://github.com/.../pull/123`.
+ async fn extract_pr_url_from_task(
+ &self,
+ task_id: Uuid,
+ ) -> Result<Option<String>, anyhow::Error> {
+ let events = repository::get_task_output(&self.pool, task_id, Some(500)).await?;
+
+ let pr_url_re = regex::Regex::new(r"https://github\.com/[^/\s]+/[^/\s]+/pull/\d+")?;
+
+ // Search from most recent events backwards for the PR URL
+ for event in events.iter().rev() {
+ if let Some(ref data) = event.event_data {
+ // Check the content field inside event_data JSON
+ if let Some(content) = data.get("content").and_then(|c| c.as_str()) {
+ if let Some(m) = pr_url_re.find(content) {
+ return Ok(Some(m.as_str().to_string()));
+ }
+ }
+ // Also check the raw JSON string representation as fallback
+ let data_str = data.to_string();
+ if let Some(m) = pr_url_re.find(&data_str) {
+ return Ok(Some(m.as_str().to_string()));
+ }
+ }
+ }
+
+ Ok(None)
+ }
}
/// Build the planning prompt for a directive.
@@ -962,10 +1031,15 @@ Then create the PR:
gh pr create --title "{title}" --body "{pr_body}" --head {directive_branch} --base {base_branch}
```
-After creating the PR, store the URL:
+IMPORTANT: After creating the PR, you MUST store the PR URL so the directive system can track it.
+
+1. Run `gh pr create` as shown above and capture its output
+2. The output will contain the PR URL (e.g., https://github.com/owner/repo/pull/123)
+3. Then run this command to store the URL:
```
-makima directive update --pr-url "<the PR URL from gh pr create output>"
+makima directive update --pr-url "https://github.com/..."
```
+Replace the URL with the actual PR URL from the `gh pr create` output. This step is CRITICAL — the PR will not be tracked by the directive system without it.
If there are merge conflicts, resolve them sensibly before pushing.
"#,