From b5811ad26a94f48ddab45251e44861f5595a7b95 Mon Sep 17 00:00:00 2001
From: soryu <soryu@soryu.co>
Date: Fri, 8 May 2026 11:29:20 +0100
Subject: feat(directives): unified contracts surface — backbone
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is the backbone PR for the unified directive workflow. A directive
holds a sequence of contracts; each contract is a spec body whose
execution drives tasks in the directive's shared worktree. Lifecycle
(Lock & Start, queue scheduler, drag-reorder) lands in follow-ups.

What's in this PR:
- Migration adds `position` (queue order) and `merge_mode`
  (shared|own_pr) columns to directive_documents. The actual table
  rename is deferred — the legacy `contracts` table from the old
  contracts system still exists, and the rename collision waits for
  Phase 5 to drop legacy contracts.
- Repository: list orders by position; create assigns next-position;
  update accepts merge_mode; new reorder_directive_document_position
  shifts siblings inside a transaction.
- HTTP: endpoints aliased under /api/v1/directives/{id}/contracts and
  /api/v1/contracts/{id}/... with a new /contracts/{id}/reorder.
- Frontend: api types renamed `DirectiveContract*` (avoiding the
  legacy `Contract` type collision); document-directives.tsx imports
  via aliases so the rest of the file is untouched.

Internal struct + table names stay `DirectiveDocument` /
`directive_documents` until the legacy contracts cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 ...60508000000_add_contract_sequencing_columns.sql | 48 ++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 makima/migrations/20260508000000_add_contract_sequencing_columns.sql

(limited to 'makima/migrations/20260508000000_add_contract_sequencing_columns.sql')

diff --git a/makima/migrations/20260508000000_add_contract_sequencing_columns.sql b/makima/migrations/20260508000000_add_contract_sequencing_columns.sql
new file mode 100644
index 0000000..a259285
--- /dev/null
+++ b/makima/migrations/20260508000000_add_contract_sequencing_columns.sql
@@ -0,0 +1,48 @@
+-- Add the contract sequencing columns to directive_documents.
+--
+-- Background: the directive_documents table was always intended to BE the
+-- user-facing "contract" concept (see migration 20260502000000:
+-- "the user calls these 'directive contracts'"). The unified directive
+-- workflow now formalises that — a directive holds a sequence of
+-- contracts; each contract is a spec body whose execution is driven by
+-- tasks in the directive's shared worktree.
+--
+-- This migration is purely additive. It does NOT rename the table —
+-- there is a legacy `contracts` table from the old contracts system
+-- (still present, archived in 20260501000000), and renaming
+-- `directive_documents → contracts` would collide with it. The actual
+-- table rename lands once the legacy table is dropped (Phase 5).
+--
+-- For now: the Rust struct, API endpoints, and frontend types are all
+-- renamed to "Contract" so the user-visible surface matches their model.
+-- The DB column names (`directive_documents`, `directive_document_id`)
+-- stay put.
+--
+-- Two new columns:
+--   * position  — integer ordering inside the directive (queue position).
+--                 Backfilled by created_at so existing data keeps the
+--                 visual order users see today.
+--   * merge_mode — 'shared' (commits go to the directive's branch) or
+--                 'own_pr' (each contract gets its own branch + PR).
+--                 Default 'shared'; per-contract toggle in the UI lifts
+--                 to 'own_pr'.
+
+ALTER TABLE directive_documents
+    ADD COLUMN position INT NOT NULL DEFAULT 0;
+
+WITH ranked AS (
+    SELECT id,
+           ROW_NUMBER() OVER (
+               PARTITION BY directive_id
+               ORDER BY created_at ASC, id ASC
+           ) - 1 AS rn
+      FROM directive_documents
+)
+UPDATE directive_documents d
+   SET position = r.rn
+  FROM ranked r
+ WHERE d.id = r.id;
+
+ALTER TABLE directive_documents
+    ADD COLUMN merge_mode VARCHAR(16) NOT NULL DEFAULT 'shared'
+    CHECK (merge_mode IN ('shared', 'own_pr'));
-- 
cgit v1.2.3

