From c0f220582cd61f0d88e42dfbc29d55b3be1e3b19 Mon Sep 17 00:00:00 2001
From: soryu <soryu@soryu.co>
Date: Sun, 8 Feb 2026 16:18:13 +0000
Subject: Fix directive deletion and stop local only on contracts

---
 .../src/components/directives/DirectiveDetail.tsx  | 188 +++++----------------
 1 file changed, 42 insertions(+), 146 deletions(-)

(limited to 'makima/frontend/src/components/directives/DirectiveDetail.tsx')

diff --git a/makima/frontend/src/components/directives/DirectiveDetail.tsx b/makima/frontend/src/components/directives/DirectiveDetail.tsx
index 06d8ba2..6bdf5aa 100644
--- a/makima/frontend/src/components/directives/DirectiveDetail.tsx
+++ b/makima/frontend/src/components/directives/DirectiveDetail.tsx
@@ -3,8 +3,6 @@ import { useNavigate } from "react-router";
 import type {
   DirectiveWithChains,
   DirectiveStatus,
-  ChainWithSteps,
-  ChainStep,
   ContractPhase,
 } from "../../lib/api";
 import { getDirective } from "../../lib/api";
@@ -32,122 +30,6 @@ const statusColors: Record<DirectiveStatus, string> = {
   failed: "text-red-400",
 };
 
-const stepStatusColors: Record<string, string> = {
-  pending: "text-[#888]",
-  running: "text-yellow-400",
-  passed: "text-green-400",
-  failed: "text-red-400",
-};
-
-const stepStatusIcons: Record<string, string> = {
-  pending: "\u25CB", // ○
-  running: "\u25D4", // ◔
-  passed: "\u25CF", // ●
-  failed: "\u2715", // ✕
-};
-
-function StepRow({ step }: { step: ChainStep }) {
-  const navigate = useNavigate();
-  const color = stepStatusColors[step.status] || "text-[#888]";
-  const icon = stepStatusIcons[step.status] || "\u25CB";
-  const summary = step.contractSummary;
-
-  return (
-    <div className="flex items-start gap-2 py-1.5 px-2 hover:bg-[rgba(117,170,252,0.05)]">
-      <span className={`font-mono text-[11px] ${color} mt-px`}>{icon}</span>
-      <div className="flex-1 min-w-0">
-        <div className="flex items-center gap-2">
-          <span className="font-mono text-[11px] text-[#dbe7ff] truncate">
-            {step.name}
-          </span>
-          <span className={`font-mono text-[9px] uppercase ${color}`}>
-            {step.status}
-          </span>
-        </div>
-        {summary && (
-          <div className="flex items-center gap-2 mt-0.5">
-            <PhaseProgressBarCompact
-              currentPhase={summary.phase as ContractPhase}
-            />
-            <span className="font-mono text-[9px] text-[#7788aa]">
-              {summary.tasksDone}/{summary.taskCount} tasks
-            </span>
-            {step.contractId && (
-              <button
-                onClick={(e) => {
-                  e.stopPropagation();
-                  navigate(`/contracts/${step.contractId}`);
-                }}
-                className="font-mono text-[9px] text-[#75aafc] hover:text-white transition-colors"
-              >
-                contract &rarr;
-              </button>
-            )}
-          </div>
-        )}
-        {!summary && step.contractId && (
-          <button
-            onClick={() => navigate(`/contracts/${step.contractId}`)}
-            className="font-mono text-[9px] text-[#75aafc] hover:text-white transition-colors mt-0.5"
-          >
-            contract &rarr;
-          </button>
-        )}
-        {step.description && (
-          <p className="font-mono text-[10px] text-[#7788aa] truncate mt-0.5">
-            {step.description}
-          </p>
-        )}
-      </div>
-    </div>
-  );
-}
-
-function ChainCard({ chainWithSteps }: { chainWithSteps: ChainWithSteps }) {
-  const chain = chainWithSteps;
-  const steps = chainWithSteps.steps || [];
-
-  return (
-    <div className="border border-dashed border-[rgba(117,170,252,0.25)] bg-[rgba(117,170,252,0.03)]">
-      <div className="p-3">
-        <div className="flex items-center justify-between mb-1">
-          <span className="font-mono text-xs text-[#dbe7ff]">
-            {chain.name}
-          </span>
-          <span className="font-mono text-[10px] text-[#7788aa] uppercase">
-            gen {chain.generation} &middot; {chain.status}
-          </span>
-        </div>
-        {chain.description && (
-          <p className="font-mono text-[11px] text-[#7788aa] mb-1">
-            {chain.description}
-          </p>
-        )}
-        <div className="flex gap-3 font-mono text-[10px] text-[#7788aa]">
-          <span>
-            {chain.completedSteps}/{chain.totalSteps} steps
-          </span>
-          {chain.failedSteps > 0 && (
-            <span className="text-red-400">{chain.failedSteps} failed</span>
-          )}
-          {chain.currentConfidence != null && (
-            <span>
-              confidence: {(chain.currentConfidence * 100).toFixed(0)}%
-            </span>
-          )}
-        </div>
-      </div>
-      {steps.length > 0 && (
-        <div className="border-t border-dashed border-[rgba(117,170,252,0.15)]">
-          {steps.map((step) => (
-            <StepRow key={step.id} step={step} />
-          ))}
-        </div>
-      )}
-    </div>
-  );
-}
-
 function JsonSection({
   label,
   data,
@@ -484,39 +366,53 @@ export function DirectiveDetail({
 
         {activeTab === "chain" && (
           <div className="space-y-4">
-            {/* Step diagram */}
-            {directive.chains.length > 0 && (
-              <div>
-                <h4 className="font-mono text-[10px] text-[#75aafc] uppercase tracking-wider mb-2">
-                  Step Dependencies
-                </h4>
-                <StepDiagram
-                  steps={directive.chains.flatMap((c) => c.steps)}
-                />
-              </div>
-            )}
-
-            {/* Chain cards */}
-            <div>
-              <h4 className="font-mono text-[10px] text-[#75aafc] uppercase tracking-wider mb-2">
-                Chains ({directive.chains.length})
-              </h4>
-              {directive.chains.length === 0 ? (
-                <p className="font-mono text-xs text-[#7788aa]">
+            {directive.chains.length === 0 ? (
+              <div className="flex flex-col items-center justify-center py-12">
+                <div className="font-mono text-[40px] text-[#333] mb-3">
+                  {directive.status === "planning" ? "\u2699" : "\u25CB"}
+                </div>
+                <p className="font-mono text-xs text-[#7788aa] text-center max-w-[300px]">
                   {directive.status === "planning"
-                    ? "Planning in progress... chains will appear when the planner completes."
+                    ? "Planning in progress... the chain will appear when the planner submits a plan."
                     : directive.status === "draft"
                       ? "No chains yet. Start the directive to begin planning."
                       : "No chains created for this directive."}
                 </p>
-              ) : (
-                <div className="space-y-2">
-                  {directive.chains.map((cws) => (
-                    <ChainCard key={cws.id} chainWithSteps={cws} />
-                  ))}
-                </div>
-              )}
-            </div>
+              </div>
+            ) : (
+              <>
+                {/* Chain metadata header */}
+                {directive.chains.map((chain) => (
+                  <div key={chain.id} className="space-y-3">
+                    <div className="flex items-center gap-3 pb-2 border-b border-dashed border-[rgba(117,170,252,0.15)]">
+                      <span className="font-mono text-xs text-[#dbe7ff]">
+                        {chain.name}
+                      </span>
+                      <span className="font-mono text-[10px] text-[#7788aa] uppercase">
+                        gen {chain.generation}
+                      </span>
+                      <span className={`font-mono text-[10px] uppercase ${
+                        chain.status === "completed" ? "text-green-400" :
+                        chain.status === "failed" ? "text-red-400" :
+                        chain.status === "running" ? "text-yellow-400" :
+                        "text-[#7788aa]"
+                      }`}>
+                        {chain.status}
+                      </span>
+                      <span className="font-mono text-[10px] text-[#7788aa] ml-auto">
+                        {chain.completedSteps}/{chain.totalSteps} steps
+                        {chain.failedSteps > 0 && (
+                          <span className="text-red-400 ml-1">
+                            ({chain.failedSteps} failed)
+                          </span>
+                        )}
+                      </span>
+                    </div>
+                    <StepDiagram steps={chain.steps} />
+                  </div>
+                ))}
+              </>
+            )}
           </div>
         )}
 
-- 
cgit v1.2.3

