Files
clawmates/crates/cm-domain/src/ids.rs
T
Omar SobhandClaude Opus 4.7 fbefc67878
ci / gates (push) Successful in 6s
ci / rust (push) Failing after 9s
ci / frontend (push) Successful in 25s
ci / e2e (push) Skipped
ci / publish (push) Skipped
slice 1: missions data model + migration
Introduce the unified `missions` tier that will replace the current
research_topics + loops split. This slice ships the data model +
backfill + skeleton REST surface; the old wizards keep working in
parallel until Slice 9's big-bang cutover.

Migration 0047 adds:
  - missions              (top-level workflow: template_kind + team +
                           schedule + status + config)
  - mission_phases        (ordered {research|coding|benchmark|
                           security_scan} phases per mission)
  - mission_tasks         (typed units of work, e.g. INT-XX cards,
                           UPSERT-keyed on (phase_id, external_id))
  - mission_artifacts     (MD/PDF/benchmark/security/diff files with
                           a pending queue for the PDF renderer worker)
  - benchmark_snapshots   (before/after pairs per iteration)

Backfill copies existing research_topics + loops rows into the new
tables as one-shot missions with the appropriate template_kind, so
Slice 2's UI can render the full history immediately.

New Rust surface:
  - cm_domain: MissionId, MissionPhaseId, MissionTaskId, MissionArtifactId
  - cm_db::repo::missions: Mission/MissionPhase/MissionTask/
    MissionArtifact structs + insert (txn-wrapped)/get/list/set_status/
    phases_for/set_phase_status/upsert_task/tasks_for/register_artifact/
    artifacts_for/next_pdf_pending/set_pdf_result
  - cm_api::routes::missions: skeleton list/create/get/set_status
    routes registered at /api/missions/*

Follow-up slices layer richer behavior (template dispatch, phase
execution, task parsing, artifact rendering) on this foundation.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-07-19 11:40:51 -07:00

97 lines
2.4 KiB
Rust

use std::fmt;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Defines a strongly-typed UUID wrapper so ids of different entities can
/// never be swapped for one another at compile time. New ids are UUIDv7 so
/// they sort by creation time in Postgres indexes.
macro_rules! define_id {
($(#[$doc:meta])* $name:ident) => {
$(#[$doc])*
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
#[serde(transparent)]
pub struct $name(Uuid);
impl $name {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self(Uuid::now_v7())
}
pub fn as_uuid(&self) -> Uuid {
self.0
}
}
impl From<Uuid> for $name {
fn from(value: Uuid) -> Self {
Self(value)
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl FromStr for $name {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(Uuid::parse_str(s)?))
}
}
};
}
define_id!(
/// A tenant workspace (team).
WorkspaceId
);
define_id!(
/// A human member of a workspace.
UserId
);
define_id!(
/// An AI agent ("claw").
AgentId
);
define_id!(
/// A chat session between humans and one agent.
SessionId
);
define_id!(
/// A single message within a session.
MessageId
);
define_id!(
/// A connected fleet node (a user's local-hardware host running the daemon).
NodeId
);
define_id!(
/// A user-driven workflow composed of one or more mission_phases.
/// Unifies research_topics + loops behind a single tier (Slice 1
/// of the missions unification).
MissionId
);
define_id!(
/// A single phase within a mission (research | coding | benchmark |
/// security_scan). Ordered via `order_idx` on the row.
MissionPhaseId
);
define_id!(
/// A typed unit of work within a phase — e.g. an INT-XX item, a
/// CVE finding, a research outcome iteration.
MissionTaskId
);
define_id!(
/// A file artifact produced by a mission phase — MD, PDF,
/// benchmark result, security report, code diff.
MissionArtifactId
);