omk 0.5.0

A Rust runtime for Kimi CLI. Turns prompts into proof-backed engineering runs with gates, worktrees, and replay.
Documentation
use anyhow::Result;
use serde_json::Value;
use std::path::Path;

use super::metadata::{GoalTaskDeliveryMetadataUpdate, GoalTaskDeliveryStatus};
use super::persist::{
    load_task_graph_value, task_graph_path, task_ids_in_value, update_goal_task_delivery_metadata,
};
use crate::runtime::goal::worktree::GoalWorktreePlan;

pub(crate) async fn ensure_worktree_delivery_targets(
    goal_dir: &Path,
    plans: &[GoalWorktreePlan],
) -> Result<()> {
    let value = load_task_graph_value(goal_dir).await?;
    let task_ids = task_ids_in_value(&value);
    for plan in plans {
        if !task_ids.contains(plan.task_id.as_str()) {
            anyhow::bail!(
                "cannot record goal worktree delivery metadata: task {} not found in {}",
                plan.task_id,
                task_graph_path(goal_dir).display()
            );
        }
    }
    Ok(())
}

pub(crate) async fn record_worktree_delivery_metadata(
    goal_dir: &Path,
    plan: &GoalWorktreePlan,
) -> Result<()> {
    let graph = load_task_graph_value(goal_dir).await?;
    let task = graph
        .get("tasks")
        .and_then(Value::as_array)
        .into_iter()
        .flatten()
        .find(|task| task.get("id").and_then(Value::as_str) == Some(plan.task_id.as_str()));
    let owner = task
        .and_then(|task| task.get("owner_role").and_then(Value::as_str))
        .map(str::to_string);
    let write_scope = task
        .and_then(|task| task.get("write_set"))
        .and_then(|value| serde_json::from_value(value.clone()).ok());

    update_goal_task_delivery_metadata(
        goal_dir,
        &plan.task_id,
        GoalTaskDeliveryMetadataUpdate {
            owner,
            write_scope,
            branch: Some(plan.branch_name.clone()),
            worktree_path: Some(plan.worktree_path.clone()),
            status: Some(GoalTaskDeliveryStatus::Planned),
            ..GoalTaskDeliveryMetadataUpdate::default()
        },
    )
    .await?;
    Ok(())
}