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 chrono::{DateTime, Utc};
use std::path::{Path, PathBuf};

use crate::runtime::goal::state::{
    GoalState, GOAL_PRD_FILE, GOAL_TECHNICAL_PLAN_FILE, GOAL_TEST_SPEC_FILE,
};
use crate::runtime::goal::task_graph::GoalTaskGraph;

const ORACLE_ARTIFACTS_DIR: &str = "artifacts/oracles";
const GREENFIELD_ACCEPTANCE_FILE: &str = "artifacts/oracles/greenfield-acceptance.md";
const GREENFIELD_DEMO_FILE: &str = "artifacts/oracles/greenfield-demo.sh";
const GREENFIELD_USAGE_FILE: &str = "artifacts/oracles/usage-examples.md";

pub(super) async fn write_goal_brief(state: &GoalState, generated_at: DateTime<Utc>) -> Result<()> {
    let body = format!(
        "# Goal Brief\n\n\
         Generated: {generated_at}\n\n\
         ## Original Goal\n\n\
         {}\n\n\
         ## Normalized Goal\n\n\
         {}\n\n\
         ## Current Scope\n\n\
         This scaffold captures intent and durable planning artifacts. Run `omk goal execute` to attach local gate evidence and a bounded Wire-backed agent wave, then `omk goal review` to attach controller review/security evidence.\n",
        state.original_goal, state.normalized_goal
    );
    crate::runtime::atomic::atomic_write(&state.state_dir.join(GOAL_PRD_FILE), body.as_bytes())
        .await
}

pub(super) async fn write_technical_plan(
    state: &GoalState,
    relevant_files: &[PathBuf],
    generated_at: DateTime<Utc>,
) -> Result<()> {
    let relevant_section = if relevant_files.is_empty() {
        String::new()
    } else {
        let lines = relevant_files
            .iter()
            .map(|p| format!("- `{}`", p.display()))
            .collect::<Vec<_>>()
            .join("\n");
        format!(
            "## Semantically Relevant Files\n\n\
             Discovered via AST analysis of function definitions against the goal description:\n\n\
             {lines}\n\n"
        )
    };

    let body = format!(
        "# Technical Plan\n\n\
         Generated: {generated_at}\n\n\
         ## Controller Phases\n\n\
         1. Intake records the original user goal.\n\
         2. Planning writes this technical plan and the goal brief.\n\
         3. Decomposition writes a task graph.\n\
         4. Verification design writes a test specification.\n\
         5. Local execution runs verification gates and refreshes proof evidence.\n\
         6. Review records controller review and security evidence.\n\
         7. Proof writes an honest not-ready proof until required execution, review, and integration evidence exists.\n\n\
         ## Execution Boundary\n\n\
         The current controller records planning task evidence, local verification task evidence, a bounded Wire-backed `goal-agent-execute` wave, agent mutation diff/changed-file evidence, post-mutation gate reruns when files change, and controller review/security evidence. The initial wave can make minimal project changes under the worker boundary, but readiness still requires specialist review loops and integration acceptance.\n\n\
         {relevant_section}\
         Goal ID: `{}`\n",
        state.goal_id
    );
    crate::runtime::atomic::atomic_write(
        &state.state_dir.join(GOAL_TECHNICAL_PLAN_FILE),
        body.as_bytes(),
    )
    .await
}

pub(super) async fn write_test_spec(
    state: &GoalState,
    task_graph: &GoalTaskGraph,
    project_dir: &Path,
    generated_at: DateTime<Utc>,
) -> Result<()> {
    let task_lines = task_graph
        .tasks
        .iter()
        .map(|task| format!("- `{}`: {}", task.id, task.acceptance.join("; ")))
        .collect::<Vec<_>>()
        .join("\n");
    let oracle =
        crate::runtime::goal::oracle::assess_goal_oracle_evidence(&state.normalized_goal, &[]);
    let oracle_lines = oracle
        .checks
        .iter()
        .map(|check| format!("- `{}`", check.name))
        .collect::<Vec<_>>()
        .join("\n");
    let compatibility_plan = compatibility_plan(&oracle, project_dir).await?;
    let body = format!(
        "# Test Spec\n\n\
         Generated: {generated_at}\n\n\
         ## Required Proof Before Ready\n\n\
         - Required gates must pass.\n\
         - A proof artifact must cite gate evidence.\n\
         - Known gaps must be empty or explicitly accepted by a human.\n\n\
         ## Oracle Criteria\n\n\
         Oracle kind: `{}`\n\n\
         Required checks before `ready`:\n\n\
         {oracle_lines}\n\n\
         ## Readiness Levels\n\n\
         - Engineering-ready: local gates, execution, review, oracle, and integration evidence support handoff.\n\
         - Product-ready: a human release owner has accepted UX, documentation, rollout, and user-facing quality beyond local engineering proof.\n\n\
         {compatibility_plan}\
         ## Scaffold Task Acceptance\n\n\
         {task_lines}\n\n\
         ## Current Status\n\n\
         `omk goal` remains `not_ready` because readiness still requires integration acceptance and specialist review loops beyond controller-owned planning, local verification, bounded agent execution, mutation evidence, post-mutation gate reruns, and controller review/security evidence.\n\n\
         Goal ID: `{}`\n",
        oracle.kind.as_str(),
        state.goal_id
    );
    crate::runtime::atomic::atomic_write(
        &state.state_dir.join(GOAL_TEST_SPEC_FILE),
        body.as_bytes(),
    )
    .await
}

pub(super) async fn write_greenfield_oracle_artifacts(
    state: &GoalState,
) -> Result<Vec<(&'static str, &'static str)>> {
    let kind = crate::runtime::goal::oracle::classify_goal_kind(&state.normalized_goal);
    if kind != crate::runtime::goal::oracle::GoalKind::Greenfield {
        return Ok(Vec::new());
    }

    tokio::fs::create_dir_all(state.state_dir.join(ORACLE_ARTIFACTS_DIR)).await?;
    write_relative(
        state,
        GREENFIELD_ACCEPTANCE_FILE,
        &format!(
            "# Greenfield Acceptance Oracle\n\n\
             Goal: {}\n\n\
             Required checks before `ready`:\n\n\
             - acceptance: user-visible behavior satisfies the goal brief.\n\
             - smoke: primary command or UI path starts without errors.\n\
             - demo: a minimal end-to-end usage path can be shown locally.\n",
            state.normalized_goal
        ),
    )
    .await?;
    write_relative(
        state,
        GREENFIELD_DEMO_FILE,
        "#!/bin/sh\nset -eu\nprintf 'Run the greenfield demo path and capture output evidence.\\n'\n",
    )
    .await?;
    write_relative(
        state,
        GREENFIELD_USAGE_FILE,
        &format!(
            "# Docs-First Usage Examples\n\n\
             Before claiming product readiness, document the primary usage path for:\n\n\
             - first run\n\
             - expected success output\n\
             - common failure or recovery path\n\n\
             Goal: {}\n",
            state.normalized_goal
        ),
    )
    .await?;

    Ok(vec![
        ("greenfield_acceptance", GREENFIELD_ACCEPTANCE_FILE),
        ("greenfield_demo", GREENFIELD_DEMO_FILE),
        ("greenfield_usage_examples", GREENFIELD_USAGE_FILE),
    ])
}

async fn compatibility_plan(
    oracle: &crate::runtime::goal::oracle::GoalOracleEvidence,
    project_dir: &Path,
) -> Result<String> {
    if !matches!(
        oracle.kind,
        crate::runtime::goal::oracle::GoalKind::Rewrite
            | crate::runtime::goal::oracle::GoalKind::Migration
            | crate::runtime::goal::oracle::GoalKind::Refactor
    ) {
        return Ok(String::new());
    }

    let surfaces =
        crate::runtime::goal::oracle::surface::detect_source_project_surfaces(project_dir).await?;
    let command_lines = if surfaces.commands.is_empty() {
        "- No source-project commands detected.\n".to_string()
    } else {
        surfaces
            .commands
            .iter()
            .map(|command| format!("- `{command}`\n"))
            .collect()
    };
    let api_lines = if surfaces.api_files.is_empty() {
        "- No source API files detected.\n".to_string()
    } else {
        surfaces
            .api_files
            .iter()
            .map(|path| format!("- `{}`\n", path.display()))
            .collect()
    };

    Ok(format!(
        "## Compatibility Test Plan\n\n\
         Source commands to preserve:\n\n\
         {command_lines}\n\
         Source API/file surfaces to compare:\n\n\
         {api_lines}\n"
    ))
}

async fn write_relative(state: &GoalState, relative: &str, contents: &str) -> Result<()> {
    crate::runtime::atomic::atomic_write(&state.state_dir.join(relative), contents.as_bytes()).await
}