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::Serialize;
use serde_json::Value;
use std::path::Path;

use super::sidecar;
use crate::runtime::goal::state::{GOAL_PROOF_FILE, GOAL_TASK_GRAPH_FILE};

pub(crate) async fn write_json_artifact<T: Serialize>(path: &Path, value: &T) -> Result<()> {
    let mut value = serde_json::to_value(value)?;
    value = crate::wire::protocol::redact_wire_secrets(&value);
    enrich_goal_json_artifact(path, &mut value).await?;

    if path
        .parent()
        .and_then(|p| p.file_name())
        .and_then(|n| n.to_str())
        .is_some()
    {
        if let Some(db) = crate::runtime::db::global_db() {
            let file_name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
            if file_name == GOAL_PROOF_FILE {
                if let Ok(proof) =
                    serde_json::from_value::<super::super::proof::GoalProof>(value.clone())
                {
                    super::super::state::db_store::save_proof_to_db(&db, &proof).await?;
                    return Ok(());
                }
            }
            if file_name == GOAL_TASK_GRAPH_FILE {
                if let Ok(graph) =
                    serde_json::from_value::<super::super::task_graph::GoalTaskGraph>(value.clone())
                {
                    super::super::state::db_store::save_task_graph_to_db(&db, &graph).await?;
                    return Ok(());
                }
            }
        }
    }

    let json = serde_json::to_string_pretty(&value)?;
    crate::runtime::atomic::atomic_write(path, json.as_bytes()).await
}

async fn enrich_goal_json_artifact(path: &Path, value: &mut Value) -> Result<()> {
    let Some(file_name) = path.file_name().and_then(|name| name.to_str()) else {
        return Ok(());
    };
    let Some(goal_dir) = path.parent() else {
        return Ok(());
    };

    match file_name {
        GOAL_TASK_GRAPH_FILE => {
            crate::runtime::goal::task_graph::preserve_delivery_metadata_in_value(goal_dir, value)
                .await
        }
        GOAL_PROOF_FILE => attach_delivery_metadata_to_proof_value(goal_dir, value).await,
        _ => Ok(()),
    }
}

async fn attach_delivery_metadata_to_proof_value(
    goal_dir: &Path,
    proof_value: &mut Value,
) -> Result<()> {
    let delivery_metadata =
        crate::runtime::goal::task_graph::load_task_delivery_metadata(goal_dir).await?;
    sidecar::remember_goal_proof_delivery_metadata_for_value(
        proof_value,
        delivery_metadata.clone(),
    );
    if delivery_metadata.is_empty() {
        return Ok(());
    }
    if let Some(proof) = proof_value.as_object_mut() {
        proof.insert(
            "delivery_metadata".to_string(),
            Value::Array(delivery_metadata),
        );
    }
    Ok(())
}