From 760516b2e7b97fa389fb3902e8d2314eea052ff0 Mon Sep 17 00:00:00 2001 From: soryu Date: Sat, 2 May 2026 15:07:33 +0100 Subject: feat: multi-document directives with ephemeral task lifecycle (#119) * feat: soryu-co/soryu - makima: Fix folder/file naming and breadcrumb hash bugs * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Frontend: render multiple documents per directive folder * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * Fix DirectiveRevision import in openapi.rs after merge * Fix document-directives.tsx merge artifacts and add inactive status --- makima/src/db/models.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'makima/src/db/models.rs') diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs index 44af939..18f3435 100644 --- a/makima/src/db/models.rs +++ b/makima/src/db/models.rs @@ -539,6 +539,13 @@ pub struct Task { /// Directive step this task executes #[serde(skip_serializing_if = "Option::is_none")] pub directive_step_id: Option, + /// Directive document this task is an artifact of. Set when the + /// orchestrator (or any task-creation path) knows which document + /// triggered the work — so when that document ships, the sidebar can + /// move its tasks alongside it under shipped/. Nullable for legacy / + /// non-directive tasks. + #[serde(skip_serializing_if = "Option::is_none")] + pub directive_document_id: Option, } impl Task { @@ -2778,6 +2785,11 @@ pub struct DirectiveStep { pub started_at: Option>, pub completed_at: Option>, pub created_at: DateTime, + /// Directive document this step belongs to. When the document ships, its + /// steps move with it under shipped/. Nullable for legacy steps and for + /// directives that don't yet have a document. + #[serde(skip_serializing_if = "Option::is_none")] + pub directive_document_id: Option, } /// Directive with its steps for detail view. @@ -2902,6 +2914,11 @@ pub struct CreateDirectiveStepRequest { /// Valid values: "simple", "specification", "execute" #[serde(default)] pub contract_type: Option, + /// Optional: attach this step to a specific directive document. When + /// omitted, the repository falls back to the directive's most-recently + /// updated active document (if any). + #[serde(default)] + pub directive_document_id: Option, } /// Request to update a directive step. @@ -2917,6 +2934,32 @@ pub struct UpdateDirectiveStepRequest { pub order_index: Option, } +// ============================================================================= +// Directive Document Types +// ============================================================================= + +/// A directive document — one of N markdown documents owned by a directive. +/// The user calls these "directive contracts". Each document has its own +/// lifecycle (draft → active → shipped → archived) and may be attached to a +/// PR. Multiple documents can be active under the same directive at once. +#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct DirectiveDocument { + pub id: Uuid, + pub directive_id: Uuid, + pub title: String, + pub body: String, + /// Status: draft, active, shipped, archived + pub status: String, + pub pr_url: Option, + pub pr_branch: Option, + pub shipped_at: Option>, + pub archived_at: Option>, + pub version: i32, + pub created_at: DateTime, + pub updated_at: DateTime, +} + // ============================================================================= // Order Types // ============================================================================= -- cgit v1.2.3