From 5bde7c2d7e099fd9c8b2615602ab1d096bd9b6be Mon Sep 17 00:00:00 2001
From: soryu <soryu@soryu.co>
Date: Tue, 28 Apr 2026 21:26:11 +0100
Subject: revert PRs #93-#98; enforce strict-linear-DAG + mandatory directive
 verify (#100)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* revert: roll back PRs #93-#98 to pre-Lexical baseline

Reverts the entire chain of directive document UI work and the homepage redesign,
restoring the working tree to the state at 3679ceb (before c8b169d / PR #93).

PRs reverted:
- #93 c8b169d feat: Document UI for directive orchestration with Lexical editor
- #94 d6f01a6 fix: compilation error and warnings already merged via PR #93
- #95 5aa3faf fix: resolve compilation error and warnings in Rust backend
- #97 d513f93 feat: document UI with contract blocks, expandable logs, and interaction controls
- #96 6366941 feat: Redesign homepage with professional PC-98 styling
- #98 d1fdfb1 feat: revert broken directive PRs, re-implement Lexical document orchestrator

The directive Document UI experiments produced fragile output and merge artifacts;
follow-up commits in this PR change orchestration to favor strictly linear DAGs and
add goal/conflict verification so future runs do not require this kind of cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(directive): strict-linear-DAG planning + mandatory `directive verify`

Tightens directive orchestration so the final PR almost never needs a hand-merge:

1. Planning prompts now strongly bias toward strictly linear DAGs.
   Parallel steps are reserved for genuinely independent work (e.g. disjoint
   modules); the default for "in doubt" is sequential. Linear chains inherit
   each previous step's worktree, so the final merge is typically just a
   rebase against the base branch.

2. New CLI command `makima directive verify` does a local in-memory
   `git merge-tree` of HEAD against `<remote>/<base>` and exits non-zero
   with a list of conflicting files if the PR would not merge cleanly.
   Pure-local — no API call, no working-tree mutation.

3. Completion / PR-creation prompts now mandate three pre-push checks:
   a. build (`cargo check` and/or `tsc --noEmit`),
   b. `makima directive verify --base <base_branch>` must exit 0, and
   c. an explicit goal-alignment self-check against the diff.
   The orchestrator is told NOT to push, create the PR, or call
   `makima directive update` until all three pass. Skipping any of them
   is documented as a directive failure.

The combination means that with a linear DAG the final PR-creation task
should almost never see a real conflict — when it does, that is treated as
a planning bug to escalate rather than something to paper over with
`-X theirs`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(frontend): TS errors pre-existing on master

- TaskSlideOutPanel: declare missing `selectedFileDiff` / `selectedFilePath`
  state hooks that were referenced everywhere but never created, and
  re-balance the JSX so the `<>...</>` fragment in the non-diff branch is
  closed (the previous indentation/braces would not parse).
- api.ts: add a `getWorktreeDiff` thin wrapper around `getTaskDiff` so
  TaskDetail's per-file click handler type-checks (the per-file slice is a
  future improvement; today both return the full task diff).
- WorktreeFilesPanel: remove unused `isClickable` local; the gating already
  reads `onFileClick` directly inline.

Run after revert: `npx tsc --noEmit` exits 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 .../document/nodes/StepsDiagramComponent.tsx       | 239 ---------------------
 1 file changed, 239 deletions(-)
 delete mode 100644 frontend/src/components/document/nodes/StepsDiagramComponent.tsx

(limited to 'frontend/src/components/document/nodes/StepsDiagramComponent.tsx')

diff --git a/frontend/src/components/document/nodes/StepsDiagramComponent.tsx b/frontend/src/components/document/nodes/StepsDiagramComponent.tsx
deleted file mode 100644
index ac1cb83..0000000
--- a/frontend/src/components/document/nodes/StepsDiagramComponent.tsx
+++ /dev/null
@@ -1,239 +0,0 @@
-import React, { useEffect, useState, useRef, useCallback } from 'react';
-import { getDirective, DirectiveStep, DirectiveWithSteps } from '../../../services/directiveApi';
-import { StepLogFeed } from './StepLogFeed';
-import './StepsDiagram.css';
-
-interface StepsDiagramComponentProps {
-  directiveId: string;
-  onExpandContract?: (step: DirectiveStep) => void;
-}
-
-type StepStatus = 'pending' | 'ready' | 'running' | 'completed' | 'failed' | 'skipped';
-
-const STATUS_LABELS: Record<string, string> = {
-  pending: 'Queued',
-  ready: 'Ready',
-  running: 'Executing',
-  completed: 'Fulfilled',
-  failed: 'Failed',
-  skipped: 'Skipped',
-};
-
-function formatTime(dateStr: string): string {
-  if (!dateStr) return '';
-  const d = new Date(dateStr);
-  return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
-}
-
-interface StepCardProps {
-  step: DirectiveStep;
-  isExpanded: boolean;
-  onToggleExpand: () => void;
-  onCollapse: () => void;
-}
-
-function StepCard({ step, isExpanded, onToggleExpand, onCollapse }: StepCardProps) {
-  const status = (step.status || 'pending').toLowerCase() as StepStatus;
-  const hasTask = !!step.taskId || !!step.contractId;
-  const canExpand = hasTask && ['running', 'completed', 'failed'].includes(status);
-
-  return (
-    <div className={`steps-diagram-card steps-diagram-card--${status} ${isExpanded ? 'steps-diagram-card--expanded' : ''}`}>
-      <div
-        className={`steps-diagram-card-header ${canExpand ? 'steps-diagram-card-header--clickable' : ''}`}
-        onClick={canExpand ? onToggleExpand : undefined}
-        role={canExpand ? 'button' : undefined}
-        tabIndex={canExpand ? 0 : undefined}
-        onKeyDown={canExpand ? (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggleExpand(); } } : undefined}
-      >
-        <span className="steps-diagram-card-name">{step.name}</span>
-        <div className="steps-diagram-card-header-right">
-          <span className={`steps-diagram-status-badge steps-diagram-status-badge--${status}`}>
-            {STATUS_LABELS[status] || status}
-          </span>
-          {canExpand && (
-            <span className={`steps-diagram-expand-icon ${isExpanded ? 'expanded' : ''}`}>
-              &#x25B6;
-            </span>
-          )}
-        </div>
-      </div>
-      {step.description && !isExpanded && (
-        <p className="steps-diagram-card-desc">{step.description}</p>
-      )}
-      <div className="steps-diagram-card-footer">
-        <span className="steps-diagram-card-index">#{step.orderIndex}</span>
-        {status === 'running' && (
-          <span className="steps-diagram-card-progress">In progress...</span>
-        )}
-        {status === 'completed' && step.completedAt && (
-          <span className="steps-diagram-card-time">
-            Completed {formatTime(step.completedAt)}
-          </span>
-        )}
-      </div>
-
-      {/* Expandable log feed */}
-      {isExpanded && hasTask && (
-        <StepLogFeed
-          taskId={step.taskId || step.contractId}
-          stepName={step.name}
-          stepStatus={status}
-          onCollapse={onCollapse}
-        />
-      )}
-    </div>
-  );
-}
-
-export function StepsDiagramComponent({ directiveId, onExpandContract }: StepsDiagramComponentProps) {
-  const [steps, setSteps] = useState<DirectiveStep[]>([]);
-  const [directiveStatus, setDirectiveStatus] = useState<string>('');
-  const [loading, setLoading] = useState(true);
-  const [error, setError] = useState<string | null>(null);
-  const [expandedStepId, setExpandedStepId] = useState<string | null>(null);
-  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
-  const prevStepCountRef = useRef(0);
-
-  const fetchSteps = useCallback(async () => {
-    try {
-      const data: DirectiveWithSteps = await getDirective(directiveId);
-      setSteps(data.steps || []);
-      setDirectiveStatus(data.status || '');
-      setError(null);
-    } catch (err) {
-      setError(err instanceof Error ? err.message : 'Failed to load contracts');
-    } finally {
-      setLoading(false);
-    }
-  }, [directiveId]);
-
-  useEffect(() => {
-    fetchSteps();
-    intervalRef.current = setInterval(fetchSteps, 5000);
-    return () => {
-      if (intervalRef.current) clearInterval(intervalRef.current);
-    };
-  }, [fetchSteps]);
-
-  // Track when new steps appear for animation
-  useEffect(() => {
-    prevStepCountRef.current = steps.length;
-  }, [steps.length]);
-
-  // Keyboard shortcut: Escape to collapse expanded step
-  useEffect(() => {
-    const handler = (e: KeyboardEvent) => {
-      if (e.key === 'Escape' && expandedStepId) {
-        setExpandedStepId(null);
-      }
-    };
-    document.addEventListener('keydown', handler);
-    return () => document.removeEventListener('keydown', handler);
-  }, [expandedStepId]);
-
-  const toggleExpand = useCallback((stepId: string) => {
-    setExpandedStepId(prev => prev === stepId ? null : stepId);
-  }, []);
-
-  const collapseExpanded = useCallback(() => {
-    setExpandedStepId(null);
-  }, []);
-
-  const completedCount = steps.filter(s => s.status?.toLowerCase() === 'completed').length;
-  const totalCount = steps.length;
-  const isActive = ['active', 'running', 'planning'].includes(directiveStatus.toLowerCase());
-  const isBuilding = isActive && steps.length === 0;
-
-  // Group steps by orderIndex
-  const groupedSteps: Map<number, DirectiveStep[]> = new Map();
-  const sortedSteps = [...steps].sort((a, b) => a.orderIndex - b.orderIndex);
-  for (const step of sortedSteps) {
-    const idx = step.orderIndex;
-    if (!groupedSteps.has(idx)) groupedSteps.set(idx, []);
-    groupedSteps.get(idx)!.push(step);
-  }
-  const orderGroups = Array.from(groupedSteps.entries()).sort((a, b) => a[0] - b[0]);
-
-  if (loading) {
-    return (
-      <div className="steps-diagram" contentEditable={false}>
-        <div className="steps-diagram-header">
-          <span className="steps-diagram-header-title">Contract Steps</span>
-          <span className="steps-diagram-header-author">Authored by Makima</span>
-        </div>
-        <div className="steps-diagram-loading">
-          <div className="steps-diagram-spinner" />
-          <span>Loading contracts...</span>
-        </div>
-      </div>
-    );
-  }
-
-  if (error) {
-    return (
-      <div className="steps-diagram" contentEditable={false}>
-        <div className="steps-diagram-header">
-          <span className="steps-diagram-header-title">Contract Steps</span>
-          <span className="steps-diagram-header-author">Authored by Makima</span>
-        </div>
-        <div className="steps-diagram-error">Failed to load contracts: {error}</div>
-      </div>
-    );
-  }
-
-  return (
-    <div className={`steps-diagram ${expandedStepId ? 'steps-diagram--has-expanded' : ''}`} contentEditable={false}>
-      <div className="steps-diagram-header">
-        <div className="steps-diagram-header-left">
-          <span className="steps-diagram-header-title">Contract Steps</span>
-          {totalCount > 0 && (
-            <span className="steps-diagram-header-count">
-              {completedCount}/{totalCount} fulfilled
-            </span>
-          )}
-        </div>
-        <span className="steps-diagram-header-author">Authored by Makima</span>
-      </div>
-
-      {isBuilding && (
-        <div className="steps-diagram-planning">
-          <div className="steps-diagram-planning-dots">
-            <span /><span /><span />
-          </div>
-          <span>Makima is drafting contracts...</span>
-        </div>
-      )}
-
-      {totalCount === 0 && !isBuilding && (
-        <div className="steps-diagram-empty">No contract steps defined yet.</div>
-      )}
-
-      {totalCount > 0 && (
-        <div className="steps-diagram-dag">
-          {orderGroups.map(([orderIndex, groupSteps], groupIdx) => (
-            <React.Fragment key={orderIndex}>
-              {groupIdx > 0 && (
-                <div className="steps-diagram-arrow">
-                  <div className="steps-diagram-arrow-line" />
-                  <div className="steps-diagram-arrow-head" />
-                </div>
-              )}
-              <div className="steps-diagram-group">
-                {groupSteps.map((step) => (
-                  <StepCard
-                    key={step.id}
-                    step={step}
-                    isExpanded={expandedStepId === step.id}
-                    onToggleExpand={() => toggleExpand(step.id)}
-                    onCollapse={collapseExpanded}
-                  />
-                ))}
-              </div>
-            </React.Fragment>
-          ))}
-        </div>
-      )}
-    </div>
-  );
-}
-- 
cgit v1.2.3

