1→import { useEffect, useState } from 'react'
     2→import { useProjectStore } from '../stores/projectStore'
     3→import { useAgentStore } from '../stores/agentStore'
     4→import {
     5→  FolderOpen,
     6→  CheckCircle,
     7→  Clock,
     8→  AlertTriangle,
     9→  Activity,
    10→  Trash2,
    11→  Pencil,
    12→  Check,
    13→  Palette,
    14→  X,
    15→} from 'lucide-react'
    16→import * as AlertDialog from '@radix-ui/react-alert-dialog'
    17→import * as Dialog from '@radix-ui/react-dialog'
    18→
    19→interface TaskStats {
    20→  completed: number
    21→  inProgress: number
    22→  blocked: number
    23→  backlog: number
    24→  qa: number
    25→}
    26→
    27→export default function Dashboard() {
    28→  const { currentProject, fetchProjects, deleteProject, updateProject } = useProjectStore()
    29→  const { activeSessions, fetchActiveSessions } = useAgentStore()
    30→  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
    31→  const [isDeleting, setIsDeleting] = useState(false)
    32→  const [showEditDialog, setShowEditDialog] = useState(false)
    33→  const [editName, setEditName] = useState('')
    34→  const [editDescription, setEditDescription] = useState('')
    35→  const [editDesignMode, setEditDesignMode] = useState<'mvp' | 'finished'>('mvp')
    36→  const [isSaving, setIsSaving] = useState(false)
    37→  const [saveSuccess, setSaveSuccess] = useState(false)
    38→  const [taskStats, setTaskStats] = useState<TaskStats>({
    39→    completed: 0,
    40→    inProgress: 0,
    41→    blocked: 0,
    42→    backlog: 0,
    43→    qa: 0,
    44→  })
    45→
    46→  useEffect(() => {
    47→    fetchProjects()
    48→    fetchActiveSessions()
    49→  }, [fetchProjects, fetchActiveSessions])
    50→
    51→  // Fetch task statistics when current project changes
    52→  useEffect(() => {
    53→    const fetchTaskStats = async () => {
    54→      if (!currentProject) return
    55→
    56→      try {
    57→        const response = await fetch(`http://localhost:8000/api/projects/${currentProject.id}/tasks`)
    58→        if (!response.ok) return
    59→
    60→        const tasks = await response.json()
    61→        const stats: TaskStats = {
    62→          completed: 0,
    63→          inProgress: 0,
    64→          blocked: 0,
    65→          backlog: 0,
    66→          qa: 0,
    67→        }
    68→
    69→        tasks.forEach((task: { status: string }) => {
    70→          switch (task.status) {
    71→            case 'done':
    72→              stats.completed++
    73→              break
    74→            case 'in_progress':
    75→              stats.inProgress++
    76→              break
    77→            case 'blocked':
    78→              stats.blocked++
    79→              break
    80→            case 'backlog':
    81→              stats.backlog++
    82→              break
    83→            case 'qa':
    84→              stats.qa++
    85→              break
    86→          }
    87→        })
    88→
    89→        setTaskStats(stats)
    90→      } catch (error) {
    91→        console.error('Failed to fetch task stats:', error)
    92→      }
    93→    }
    94→
    95→    fetchTaskStats()
    96→  }, [currentProject])
    97→
    98→  const handleDeleteProject = async () => {
    99→    if (!currentProject) return
   100→    setIsDeleting(true)
   101→    try {
   102→      await deleteProject(currentProject.id)
   103→      setShowDeleteDialog(false)
   104→    } catch (error) {
   105→      console.error('Failed to delete project:', error)
   106→    } finally {
   107→      setIsDeleting(false)
   108→    }
   109→  }
   110→
   111→  const handleOpenEditDialog = () => {
   112→    if (currentProject) {
   113→      setEditName(currentProject.name)
   114→      setEditDescription(currentProject.description || '')
   115→      setEditDesignMode((currentProject.design_mode as 'mvp' | 'finished') || 'mvp')
   116→      setSaveSuccess(false)
   117→      setShowEditDialog(true)
   118→    }
   119→  }
   120→
   121→  const handleSaveProject = async () => {
   122→    if (!currentProject) return
   123→    setIsSaving(true)
   124→    setSaveSuccess(false)
   125→    try {
   126→      const response = await fetch(`http://localhost:8000/api/projects/${currentProject.id}`, {
   127→        method: 'PUT',
   128→        headers: { 'Content-Type': 'application/json' },
   129→        body: JSON.stringify({ name: editName, description: editDescription, design_mode: editDesignMode }),
   130→      })
   131→      if (!response.ok) throw new Error('Failed to update project')
   132→      const updated = await response.json()
   133→      updateProject(currentProject.id, updated)
   134→      setSaveSuccess(true)
   135→      setTimeout(() => {
   136→        setShowEditDialog(false)
   137→        setSaveSuccess(false)
   138→      }, 1000)
   139→    } catch (error) {
   140→      console.error('Failed to save project:', error)
   141→    } finally {
   142→      setIsSaving(false)
   143→    }
   144→  }
   145→
   146→  if (!currentProject) {
   147→    return (
   148→

   149→        <FolderOpen size={64} className="text-slate-600 mb-4" />
   150→

   151→          No Project Selected
   152→

   153→

   154→          Select a project from the sidebar or create a new one to get started.
   155→

   156→

   157→    )
   158→  }
   159→
   160→  const stats = [
   161→    {
   162→      label: 'Tasks Completed',
   163→      value: taskStats.completed,
   164→      icon: CheckCircle,
   165→      color: 'text-green-400',
   166→    },
   167→    {
   168→      label: 'Tasks In Progress',
   169→      value: taskStats.inProgress,
   170→      icon: Clock,
   171→      color: 'text-accent',
   172→    },
   173→    {
   174→      label: 'Blocked Tasks',
   175→      value: taskStats.blocked,
   176→      icon: AlertTriangle,
   177→      color: 'text-warning',
   178→    },
   179→    {
   180→      label: 'Active Agents',
   181→      value: activeSessions.filter((s) => s.status === 'running').length,
   182→      icon: Activity,
   183→      color: 'text-primary-400',
   184→    },
   185→  ]
   186→
   187→  return (
   188→

   189→      {/* Project Header */}
   190→

   191→

   192→

   193→
{currentProject.name}

   194→            {/* Design Mode Badge */}
   195→
   202→              <Palette size={12} />
   203→              {currentProject.design_mode === 'finished' ? 'Finished Mode' : 'MVP Mode'}
   204→
   205→

   206→          {currentProject.description && (
   207→
{currentProject.description}

   208→          )}
   209→

   210→

   211→          {/* Edit Button and Dialog */}
   212→          <Dialog.Root open={showEditDialog} onOpenChange={setShowEditDialog}>
   213→            <Dialog.Trigger asChild>
   214→              <button
   215→                onClick={handleOpenEditDialog}
   216→                className="flex items-center gap-2 px-3 py-2 text-sm text-slate-400 hover:text-accent hover:bg-accent/10 rounded-lg transition-colors"
   217→                title="Edit Project Settings"
   218→              >
   219→                <Pencil size={16} />
   220→                Edit
   221→              </button>
   222→            </Dialog.Trigger>
   223→            <Dialog.Portal>
   224→              <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   225→              <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">
   226→

   227→                  <Dialog.Title className="text-xl font-semibold text-white">
   228→                    Edit Project Settings
   229→                  </Dialog.Title>
   230→                  <Dialog.Close asChild>
   231→                    <button className="p-1 text-slate-400 hover:text-white hover:bg-slate-700 rounded transition-colors" aria-label="Close">
   232→                      <X size={20} />
   233→                    </button>
   234→                  </Dialog.Close>
   235→

   236→                <Dialog.Description className="mt-2 text-slate-400">
   237→                  Update your project name, description, and design mode.
   238→                </Dialog.Description>
   239→

   240→

   241→                    Project Name
   242→                    <input
   243→                      type="text"
   244→                      value={editName}
   245→                      onChange={(e) => setEditName(e.target.value)}
   246→                      className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent"
   247→                      placeholder="Enter project name"
   248→                    />
   249→

   250→

   251→                    Description
   252→                    <textarea
   253→                      value={editDescription}
   254→                      onChange={(e) => setEditDescription(e.target.value)}
   255→                      rows={3}
   256→                      className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent resize-none"
   257→                      placeholder="Enter project description"
   258→                    />
   259→

   260→

   261→                    Design Mode
   262→

   263→                      <button
   264→                        type="button"
   265→                        onClick={() => setEditDesignMode('mvp')}
   266→                        className={`p-3 rounded-lg border text-left transition-colors ${
   267→                          editDesignMode === 'mvp'
   268→                            ? 'border-amber-500 bg-amber-500/10'
   269→                            : 'border-slate-700 hover:border-slate-600'
   270→                        }`}
   271→                      >
   272→
MVP

   273→
Functional drafts OK

   274→                      </button>
   275→                      <button
   276→                        type="button"
   277→                        onClick={() => setEditDesignMode('finished')}
   278→                        className={`p-3 rounded-lg border text-left transition-colors ${
   279→                          editDesignMode === 'finished'
   280→                            ? 'border-accent bg-accent/10'
   281→                            : 'border-slate-700 hover:border-slate-600'
   282→                        }`}
   283→                      >
   284→
Finished

   285→
Polished required

   286→                      </button>
   287→

   288→

   289→

   290→

   291→                  <Dialog.Close asChild>
   292→                    <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
   293→                      Cancel
   294→                    </button>
   295→                  </Dialog.Close>
   296→                  <button
   297→                    onClick={handleSaveProject}
   298→                    disabled={isSaving || !editName.trim()}
   299→                    className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   300→                  >
   301→                    {saveSuccess ? (
   302→                      <>
   303→                        <Check size={16} />
   304→                        Saved!
   305→                      </>
   306→                    ) : isSaving ? (
   307→                      'Saving...'
   308→                    ) : (
   309→                      'Save Changes'
   310→                    )}
   311→                  </button>
   312→

   313→              </Dialog.Content>
   314→            </Dialog.Portal>
   315→          </Dialog.Root>
   316→
   317→          {/* Delete Button and Dialog */}
   318→          <AlertDialog.Root open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
   319→          <AlertDialog.Trigger asChild>
   320→            <button
   321→              className="flex items-center gap-2 px-3 py-2 text-sm text-slate-400 hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
   322→              title="Delete Project"
   323→            >
   324→              <Trash2 size={16} />
   325→              Delete
   326→            </button>
   327→          </AlertDialog.Trigger>
   328→          <AlertDialog.Portal>
   329→            <AlertDialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   330→            <AlertDialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">
   331→              <AlertDialog.Title className="text-xl font-semibold text-white">
   332→                Delete Project
   333→              </AlertDialog.Title>
   334→              <AlertDialog.Description className="mt-3 text-slate-400">
   335→                Are you sure you want to delete {currentProject.name}?
   336→                This action cannot be undone. All project data, tasks, and history will be permanently deleted.
   337→              </AlertDialog.Description>
   338→

   339→                <AlertDialog.Cancel asChild>
   340→                  <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
   341→                    Cancel
   342→                  </button>
   343→                </AlertDialog.Cancel>
   344→                <AlertDialog.Action asChild>
   345→                  <button
   346→                    onClick={handleDeleteProject}
   347→                    disabled={isDeleting}
   348→                    className="px-4 py-2 text-sm bg-destructive hover:bg-destructive/80 text-white rounded-lg transition-colors disabled:opacity-50"
   349→                  >
   350→                    {isDeleting ? 'Deleting...' : 'Delete Project'}
   351→                  </button>
   352→                </AlertDialog.Action>
   353→

   354→            </AlertDialog.Content>
   355→          </AlertDialog.Portal>
   356→        </AlertDialog.Root>
   357→

   358→

   359→
   360→      {/* Stats Grid */}
   361→

   362→        {stats.map((stat) => {
   363→          const Icon = stat.icon
   364→          return (
   365→

   369→

   370→                <Icon className={stat.color} size={24} />
   371→

   372→
{stat.label}

   373→
{stat.value}

   374→

   375→

   376→

   377→          )
   378→        })}
   379→

   380→
   381→      {/* Phase Progress */}
   382→

   383→
Phase Progress

   384→

   385→

   386→

   387→              Phase {currentProject.current_phase}
   388→              {currentProject.total_phases} total
   389→

   390→

   391→              <div
   392→                className="h-full bg-accent transition-all duration-500"
   393→                style={{
   394→                  width: `${(currentProject.current_phase / currentProject.total_phases) * 100}%`,
   395→                }}
   396→              />
   397→

   398→

   399→
   400→            {Math.round((currentProject.current_phase / currentProject.total_phases) * 100)}%
   401→
   402→

   403→

   404→
   405→      {/* Recent Activity */}
   406→

   407→
Recent Activity

   408→

   409→          {activeSessions.length === 0 ? (
   410→
No recent activity

   411→          ) : (
   412→            activeSessions.slice(0, 5).map((session) => (
   413→

   417→

   418→                  <div
   419→                    className={`w-2 h-2 rounded-full ${
   420→                      session.status === 'running'
   421→                        ? 'bg-accent animate-pulse'
   422→                        : session.status === 'completed'
   423→                        ? 'bg-green-400'
   424→                        : session.status === 'failed'
   425→                        ? 'bg-error'
   426→                        : 'bg-slate-500'
   427→                    }`}
   428→                  />
   429→                  {session.agent_type.replace('_', ' ')} Agent
   430→

   431→                {session.status}
   432→

   433→            ))
   434→          )}
   435→

   436→

   437→

   438→  )
   439→}
   440→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import { useEffect, useState } from 'react'
import { useProjectStore } from '../stores/projectStore'
import { useAgentStore } from '../stores/agentStore'
import {
  FolderOpen,
  CheckCircle,
  Clock,
  AlertTriangle,
  Activity,
  Trash2,
  Pencil,
  Check,
  Palette,
  X,
} from 'lucide-react'
import * as AlertDialog from '@radix-ui/react-alert-dialog'
import * as Dialog from '@radix-ui/react-dialog'

interface TaskStats {
  completed: number
  inProgress: number
  blocked: number
  backlog: number
  qa: number
}

export default function Dashboard() {
  const { currentProject, fetchProjects, deleteProject, updateProject } = useProjectStore()
  const { activeSessions, fetchActiveSessions } = useAgentStore()
  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
  const [isDeleting, setIsDeleting] = useState(false)
  const [showEditDialog, setShowEditDialog] = useState(false)
  const [editName, setEditName] = useState('')
  const [editDescription, setEditDescription] = useState('')
  const [editDesignMode, setEditDesignMode] = useState<'mvp' | 'finished'>('mvp')
  const [isSaving, setIsSaving] = useState(false)
  const [saveSuccess, setSaveSuccess] = useState(false)
  const [taskStats, setTaskStats] = useState<TaskStats>({
    completed: 0,
    inProgress: 0,
    blocked: 0,
    backlog: 0,
    qa: 0,
  })

  useEffect(() => {
    fetchProjects()
    fetchActiveSessions()
  }, [fetchProjects, fetchActiveSessions])

  // Fetch task statistics when current project changes
  useEffect(() => {
    const fetchTaskStats = async () => {
      if (!currentProject) return

      try {
        const response = await fetch(`http://localhost:8000/api/projects/${currentProject.id}/tasks`)
        if (!response.ok) return

        const tasks = await response.json()
        const stats: TaskStats = {
          completed: 0,
          inProgress: 0,
          blocked: 0,
          backlog: 0,
          qa: 0,
        }

        tasks.forEach((task: { status: string }) => {
          switch (task.status) {
            case 'done':
              stats.completed++
              break
            case 'in_progress':
              stats.inProgress++
              break
            case 'blocked':
              stats.blocked++
              break
            case 'backlog':
              stats.backlog++
              break
            case 'qa':
              stats.qa++
              break
          }
        })

        setTaskStats(stats)
      } catch (error) {
        console.error('Failed to fetch task stats:', error)
      }
    }

    fetchTaskStats()
  }, [currentProject])

  const handleDeleteProject = async () => {
    if (!currentProject) return
    setIsDeleting(true)
    try {
      await deleteProject(currentProject.id)
      setShowDeleteDialog(false)
    } catch (error) {
      console.error('Failed to delete project:', error)
    } finally {
      setIsDeleting(false)
    }
  }

  const handleOpenEditDialog = () => {
    if (currentProject) {
      setEditName(currentProject.name)
      setEditDescription(currentProject.description || '')
      setEditDesignMode((currentProject.design_mode as 'mvp' | 'finished') || 'mvp')
      setSaveSuccess(false)
      setShowEditDialog(true)
    }
  }

  const handleSaveProject = async () => {
    if (!currentProject) return
    setIsSaving(true)
    setSaveSuccess(false)
    try {
      const response = await fetch(`http://localhost:8000/api/projects/${currentProject.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: editName, description: editDescription, design_mode: editDesignMode }),
      })
      if (!response.ok) throw new Error('Failed to update project')
      const updated = await response.json()
      updateProject(currentProject.id, updated)
      setSaveSuccess(true)
      setTimeout(() => {
        setShowEditDialog(false)
        setSaveSuccess(false)
      }, 1000)
    } catch (error) {
      console.error('Failed to save project:', error)
    } finally {
      setIsSaving(false)
    }
  }

  if (!currentProject) {
    return (

        <FolderOpen size={64} className="text-slate-600 mb-4" />

          No Project Selected

          Select a project from the sidebar or create a new one to get started.

    )
  }

  const stats = [
    {
      label: 'Tasks Completed',
      value: taskStats.completed,
      icon: CheckCircle,
      color: 'text-green-400',
    },
    {
      label: 'Tasks In Progress',
      value: taskStats.inProgress,
      icon: Clock,
      color: 'text-accent',
    },
    {
      label: 'Blocked Tasks',
      value: taskStats.blocked,
      icon: AlertTriangle,
      color: 'text-warning',
    },
    {
      label: 'Active Agents',
      value: activeSessions.filter((s) => s.status === 'running').length,
      icon: Activity,
      color: 'text-primary-400',
    },
  ]

  return (

      {/* Project Header */}

{currentProject.name}

            {/* Design Mode Badge */}

              <Palette size={12} />
              {currentProject.design_mode === 'finished' ? 'Finished Mode' : 'MVP Mode'}

          {currentProject.description && (

{currentProject.description}

          )}

          {/* Edit Button and Dialog */}
          <Dialog.Root open={showEditDialog} onOpenChange={setShowEditDialog}>
            <Dialog.Trigger asChild>
              <button
                onClick={handleOpenEditDialog}
                className="flex items-center gap-2 px-3 py-2 text-sm text-slate-400 hover:text-accent hover:bg-accent/10 rounded-lg transition-colors"
                title="Edit Project Settings"
              >
                <Pencil size={16} />
                Edit
              </button>
            </Dialog.Trigger>
            <Dialog.Portal>
              <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
              <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">

                  <Dialog.Title className="text-xl font-semibold text-white">
                    Edit Project Settings
                  </Dialog.Title>
                  <Dialog.Close asChild>
                    <button className="p-1 text-slate-400 hover:text-white hover:bg-slate-700 rounded transition-colors" aria-label="Close">
                      <X size={20} />
                    </button>
                  </Dialog.Close>

                <Dialog.Description className="mt-2 text-slate-400">
                  Update your project name, description, and design mode.
                </Dialog.Description>

                    Project Name
                    <input
                      type="text"
                      value={editName}
                      onChange={(e) => setEditName(e.target.value)}
                      className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent"
                      placeholder="Enter project name"
                    />

                    Description
                    <textarea
                      value={editDescription}
                      onChange={(e) => setEditDescription(e.target.value)}
                      rows={3}
                      className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent resize-none"
                      placeholder="Enter project description"
                    />

                    Design Mode

                      <button
                        type="button"
                        onClick={() => setEditDesignMode('mvp')}
                        className={`p-3 rounded-lg border text-left transition-colors ${
                          editDesignMode === 'mvp'
                            ? 'border-amber-500 bg-amber-500/10'
                            : 'border-slate-700 hover:border-slate-600'
                        }`}
                      >

MVP

Functional drafts OK

                      </button>
                      <button
                        type="button"
                        onClick={() => setEditDesignMode('finished')}
                        className={`p-3 rounded-lg border text-left transition-colors ${
                          editDesignMode === 'finished'
                            ? 'border-accent bg-accent/10'
                            : 'border-slate-700 hover:border-slate-600'
                        }`}
                      >

Finished

Polished required

                      </button>

                  <Dialog.Close asChild>
                    <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
                      Cancel
                    </button>
                  </Dialog.Close>
                  <button
                    onClick={handleSaveProject}
                    disabled={isSaving || !editName.trim()}
                    className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
                  >
                    {saveSuccess ? (
                      <>
                        <Check size={16} />
                        Saved!
                      </>
                    ) : isSaving ? (
                      'Saving...'
                    ) : (
                      'Save Changes'
                    )}
                  </button>

              </Dialog.Content>
            </Dialog.Portal>
          </Dialog.Root>

          {/* Delete Button and Dialog */}
          <AlertDialog.Root open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
          <AlertDialog.Trigger asChild>
            <button
              className="flex items-center gap-2 px-3 py-2 text-sm text-slate-400 hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
              title="Delete Project"
            >
              <Trash2 size={16} />
              Delete
            </button>
          </AlertDialog.Trigger>
          <AlertDialog.Portal>
            <AlertDialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
            <AlertDialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">
              <AlertDialog.Title className="text-xl font-semibold text-white">
                Delete Project
              </AlertDialog.Title>
              <AlertDialog.Description className="mt-3 text-slate-400">
                Are you sure you want to delete {currentProject.name}?
                This action cannot be undone. All project data, tasks, and history will be permanently deleted.
              </AlertDialog.Description>

                <AlertDialog.Cancel asChild>
                  <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
                    Cancel
                  </button>
                </AlertDialog.Cancel>
                <AlertDialog.Action asChild>
                  <button
                    onClick={handleDeleteProject}
                    disabled={isDeleting}
                    className="px-4 py-2 text-sm bg-destructive hover:bg-destructive/80 text-white rounded-lg transition-colors disabled:opacity-50"
                  >
                    {isDeleting ? 'Deleting...' : 'Delete Project'}
                  </button>
                </AlertDialog.Action>

            </AlertDialog.Content>
          </AlertDialog.Portal>
        </AlertDialog.Root>

      {/* Stats Grid */}

        {stats.map((stat) => {
          const Icon = stat.icon
          return (

                <Icon className={stat.color} size={24} />

{stat.label}

{stat.value}

          )
        })}

      {/* Phase Progress */}

Phase Progress

              Phase {currentProject.current_phase}
              {currentProject.total_phases} total

              <div
                className="h-full bg-accent transition-all duration-500"
                style={{
                  width: `${(currentProject.current_phase / currentProject.total_phases) * 100}%`,
                }}
              />

            {Math.round((currentProject.current_phase / currentProject.total_phases) * 100)}%

      {/* Recent Activity */}

Recent Activity

          {activeSessions.length === 0 ? (

No recent activity

          ) : (
            activeSessions.slice(0, 5).map((session) => (

                  {session.agent_type.replace('_', ' ')} Agent

                {session.status}

            ))
          )}

  )
}


1→import { useState, useEffect } from 'react'
     2→import { Brain, Globe, Server, Plus, Search, Trash2, X } from 'lucide-react'
     3→import * as Dialog from '@radix-ui/react-dialog'
     4→import * as AlertDialog from '@radix-ui/react-alert-dialog'
     5→import { useProjectStore } from '../stores/projectStore'
     6→
     7→type MemoryTab = 'project' | 'global' | 'infrastructure'
     8→
     9→interface ProjectMemoryItem {
    10→  id: number
    11→  project_id: number
    12→  type: string
    13→  content: string
    14→  metadata: Record<string, unknown> | null
    15→  created_at: string
    16→}
    17→
    18→interface GlobalMemoryItem {
    19→  id: number
    20→  type: string
    21→  content: string
    22→  metadata: Record<string, unknown> | null
    23→  usage_count: number
    24→  created_at: string
    25→}
    26→
    27→interface InfrastructureItem {
    28→  id: number
    29→  name: string
    30→  type: string
    31→  config: Record<string, unknown>
    32→  projects: number[] | null
    33→  created_at: string
    34→  updated_at: string
    35→}
    36→
    37→const API_BASE = 'http://localhost:8000/api/memory'
    38→
    39→export default function MemoryManager() {
    40→  const { currentProject } = useProjectStore()
    41→  const [activeTab, setActiveTab] = useState<MemoryTab>('project')
    42→  const [searchQuery, setSearchQuery] = useState('')
    43→
    44→  // Data states
    45→  const [projectMemory, setProjectMemory] = useState<ProjectMemoryItem[]>([])
    46→  const [globalMemory, setGlobalMemory] = useState<GlobalMemoryItem[]>([])
    47→  const [infrastructure, setInfrastructure] = useState<InfrastructureItem[]>([])
    48→  const [isLoading, setIsLoading] = useState(false)
    49→
    50→  // Dialog states
    51→  const [showAddDialog, setShowAddDialog] = useState(false)
    52→  const [newItemType, setNewItemType] = useState('')
    53→  const [newItemContent, setNewItemContent] = useState('')
    54→  const [newItemName, setNewItemName] = useState('')
    55→  const [isSaving, setIsSaving] = useState(false)
    56→
    57→  // Delete dialog states
    58→  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
    59→  const [itemToDelete, setItemToDelete] = useState<{ id: number; type: MemoryTab } | null>(null)
    60→  const [isDeleting, setIsDeleting] = useState(false)
    61→
    62→  const tabs = [
    63→    { id: 'project' as const, label: 'Project Memory', icon: Brain },
    64→    { id: 'global' as const, label: 'Global Memory', icon: Globe },
    65→    { id: 'infrastructure' as const, label: 'Infrastructure', icon: Server },
    66→  ]
    67→
    68→  // Fetch data based on active tab
    69→  useEffect(() => {
    70→    const fetchData = async () => {
    71→      setIsLoading(true)
    72→      try {
    73→        if (activeTab === 'project' && currentProject) {
    74→          const response = await fetch(`${API_BASE}/project/${currentProject.id}`)
    75→          if (response.ok) {
    76→            const data = await response.json()
    77→            setProjectMemory(data)
    78→          }
    79→        } else if (activeTab === 'global') {
    80→          const response = await fetch(`${API_BASE}/global`)
    81→          if (response.ok) {
    82→            const data = await response.json()
    83→            setGlobalMemory(data)
    84→          }
    85→        } else if (activeTab === 'infrastructure') {
    86→          const response = await fetch(`${API_BASE}/infrastructure`)
    87→          if (response.ok) {
    88→            const data = await response.json()
    89→            setInfrastructure(data)
    90→          }
    91→        }
    92→      } catch (error) {
    93→        console.error('Failed to fetch memory items:', error)
    94→      } finally {
    95→        setIsLoading(false)
    96→      }
    97→    }
    98→    fetchData()
    99→  }, [activeTab, currentProject])
   100→
   101→  const getTypeOptions = () => {
   102→    switch (activeTab) {
   103→      case 'project':
   104→        return ['insight', 'pattern', 'gotcha', 'codebase_map']
   105→      case 'global':
   106→        return ['preference', 'pattern', 'solution']
   107→      case 'infrastructure':
   108→        return ['server', 'docker', 'database', 'deployment']
   109→      default:
   110→        return []
   111→    }
   112→  }
   113→
   114→  const handleOpenAddDialog = () => {
   115→    setNewItemType(getTypeOptions()[0] || '')
   116→    setNewItemContent('')
   117→    setNewItemName('')
   118→    setShowAddDialog(true)
   119→  }
   120→
   121→  const handleAddItem = async () => {
   122→    if (!newItemType || (!newItemContent && activeTab !== 'infrastructure')) return
   123→
   124→    setIsSaving(true)
   125→    try {
   126→      let response: Response
   127→
   128→      if (activeTab === 'project' && currentProject) {
   129→        response = await fetch(`${API_BASE}/project/${currentProject.id}`, {
   130→          method: 'POST',
   131→          headers: { 'Content-Type': 'application/json' },
   132→          body: JSON.stringify({ type: newItemType, content: newItemContent }),
   133→        })
   134→        if (response.ok) {
   135→          const newItem = await response.json()
   136→          setProjectMemory([...projectMemory, newItem])
   137→        }
   138→      } else if (activeTab === 'global') {
   139→        response = await fetch(`${API_BASE}/global`, {
   140→          method: 'POST',
   141→          headers: { 'Content-Type': 'application/json' },
   142→          body: JSON.stringify({ type: newItemType, content: newItemContent }),
   143→        })
   144→        if (response.ok) {
   145→          const newItem = await response.json()
   146→          setGlobalMemory([...globalMemory, newItem])
   147→        }
   148→      } else if (activeTab === 'infrastructure') {
   149→        response = await fetch(`${API_BASE}/infrastructure`, {
   150→          method: 'POST',
   151→          headers: { 'Content-Type': 'application/json' },
   152→          body: JSON.stringify({
   153→            name: newItemName,
   154→            type: newItemType,
   155→            config: { content: newItemContent }
   156→          }),
   157→        })
   158→        if (response.ok) {
   159→          const newItem = await response.json()
   160→          setInfrastructure([...infrastructure, newItem])
   161→        }
   162→      }
   163→
   164→      setShowAddDialog(false)
   165→    } catch (error) {
   166→      console.error('Failed to add memory item:', error)
   167→    } finally {
   168→      setIsSaving(false)
   169→    }
   170→  }
   171→
   172→  const handleDeleteClick = (id: number, type: MemoryTab) => {
   173→    setItemToDelete({ id, type })
   174→    setShowDeleteDialog(true)
   175→  }
   176→
   177→  const handleDeleteConfirm = async () => {
   178→    if (!itemToDelete) return
   179→
   180→    setIsDeleting(true)
   181→    try {
   182→      let endpoint: string
   183→
   184→      if (itemToDelete.type === 'project' && currentProject) {
   185→        endpoint = `${API_BASE}/project/${currentProject.id}/${itemToDelete.id}`
   186→      } else if (itemToDelete.type === 'global') {
   187→        endpoint = `${API_BASE}/global/${itemToDelete.id}`
   188→      } else {
   189→        endpoint = `${API_BASE}/infrastructure/${itemToDelete.id}`
   190→      }
   191→
   192→      const response = await fetch(endpoint, { method: 'DELETE' })
   193→
   194→      if (response.ok || response.status === 204) {
   195→        if (itemToDelete.type === 'project') {
   196→          setProjectMemory(projectMemory.filter(item => item.id !== itemToDelete.id))
   197→        } else if (itemToDelete.type === 'global') {
   198→          setGlobalMemory(globalMemory.filter(item => item.id !== itemToDelete.id))
   199→        } else {
   200→          setInfrastructure(infrastructure.filter(item => item.id !== itemToDelete.id))
   201→        }
   202→      }
   203→
   204→      setShowDeleteDialog(false)
   205→      setItemToDelete(null)
   206→    } catch (error) {
   207→      console.error('Failed to delete memory item:', error)
   208→    } finally {
   209→      setIsDeleting(false)
   210→    }
   211→  }
   212→
   213→  const filterItems = <T extends { content?: string; name?: string; type: string }>(items: T[]) => {
   214→    if (!searchQuery) return items
   215→    const query = searchQuery.toLowerCase()
   216→    return items.filter(item =>
   217→      item.content?.toLowerCase().includes(query) ||
   218→      item.name?.toLowerCase().includes(query) ||
   219→      item.type.toLowerCase().includes(query)
   220→    )
   221→  }
   222→
   223→  const filteredProjectMemory = filterItems(projectMemory)
   224→  const filteredGlobalMemory = filterItems(globalMemory)
   225→  const filteredInfrastructure = filterItems(infrastructure)
   226→
   227→  return (
   228→

   229→      {/* Header */}
   230→

   231→
Memory Manager

   232→        <button
   233→          onClick={handleOpenAddDialog}
   234→          className="btn-accent flex items-center gap-2"
   235→        >
   236→          <Plus size={18} />
   237→          Add Memory Item
   238→        </button>
   239→

   240→
   241→      {/* Tabs */}
   242→

   243→        {tabs.map((tab) => {
   244→          const Icon = tab.icon
   245→          return (
   246→            <button
   247→              key={tab.id}
   248→              onClick={() => setActiveTab(tab.id)}
   249→              className={`flex items-center gap-2 px-4 py-2 rounded-md transition-colors ${
   250→                activeTab === tab.id
   251→                  ? 'bg-primary-700 text-white'
   252→                  : 'text-slate-400 hover:text-white'
   253→              }`}
   254→            >
   255→              <Icon size={16} />
   256→              {tab.label}
   257→            </button>
   258→          )
   259→        })}
   260→

   261→
   262→      {/* Search */}
   263→

   264→        <Search
   265→          size={18}
   266→          className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400"
   267→        />
   268→        <input
   269→          type="text"
   270→          value={searchQuery}
   271→          onChange={(e) => setSearchQuery(e.target.value)}
   272→          placeholder="Search memory items..."
   273→          className="w-full pl-10 pr-4 py-2 bg-slate-800 border border-slate-700 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent"
   274→        />
   275→

   276→
   277→      {/* Content */}
   278→

   279→        {isLoading ? (
   280→
Loading...

   281→        ) : (
   282→          <>
   283→            {activeTab === 'project' && (
   284→

   285→                {filteredProjectMemory.length === 0 ? (
   286→                  <EmptyState
   287→                    title="No Project Memory"
   288→                    description="Memory items from your current project will appear here."
   289→                  />
   290→                ) : (
   291→                  filteredProjectMemory.map(item => (
   292→                    <MemoryCard
   293→                      key={item.id}
   294→                      id={item.id}
   295→                      type={item.type}
   296→                      content={item.content}
   297→                      createdAt={item.created_at}
   298→                      onDelete={() => handleDeleteClick(item.id, 'project')}
   299→                    />
   300→                  ))
   301→                )}
   302→

   303→            )}
   304→
   305→            {activeTab === 'global' && (
   306→

   307→                {filteredGlobalMemory.length === 0 ? (
   308→                  <EmptyState
   309→                    title="No Global Memory"
   310→                    description="Cross-project patterns and preferences will appear here."
   311→                  />
   312→                ) : (
   313→                  filteredGlobalMemory.map(item => (
   314→                    <MemoryCard
   315→                      key={item.id}
   316→                      id={item.id}
   317→                      type={item.type}
   318→                      content={item.content}
   319→                      createdAt={item.created_at}
   320→                      usageCount={item.usage_count}
   321→                      onDelete={() => handleDeleteClick(item.id, 'global')}
   322→                    />
   323→                  ))
   324→                )}
   325→

   326→            )}
   327→
   328→            {activeTab === 'infrastructure' && (
   329→

   330→                {filteredInfrastructure.length === 0 ? (
   331→                  <EmptyState
   332→                    title="No Infrastructure Config"
   333→                    description="Server and deployment configurations will appear here."
   334→                  />
   335→                ) : (
   336→                  filteredInfrastructure.map(item => (
   337→                    <InfrastructureCard
   338→                      key={item.id}
   339→                      id={item.id}
   340→                      name={item.name}
   341→                      type={item.type}
   342→                      config={item.config}
   343→                      createdAt={item.created_at}
   344→                      onDelete={() => handleDeleteClick(item.id, 'infrastructure')}
   345→                    />
   346→                  ))
   347→                )}
   348→

   349→            )}
   350→          </>
   351→        )}
   352→

   353→
   354→      {/* Add Memory Dialog */}
   355→      <Dialog.Root open={showAddDialog} onOpenChange={setShowAddDialog}>
   356→        <Dialog.Portal>
   357→          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   358→          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">
   359→

   360→              <Dialog.Title className="text-xl font-semibold text-white">
   361→                Add {activeTab === 'project' ? 'Project' : activeTab === 'global' ? 'Global' : 'Infrastructure'} Memory
   362→              </Dialog.Title>
   363→              <Dialog.Close asChild>
   364→                <button className="p-1 text-slate-400 hover:text-white hover:bg-slate-700 rounded transition-colors" aria-label="Close">
   365→                  <X size={20} />
   366→                </button>
   367→              </Dialog.Close>
   368→

   369→
   370→

   371→              {activeTab === 'infrastructure' && (
   372→

   373→                  Name *
   374→                  <input
   375→                    type="text"
   376→                    value={newItemName}
   377→                    onChange={(e) => setNewItemName(e.target.value)}
   378→                    className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent"
   379→                    placeholder="Enter config name"
   380→                  />
   381→

   382→              )}
   383→
   384→

   385→                Type *
   386→                <select
   387→                  value={newItemType}
   388→                  onChange={(e) => setNewItemType(e.target.value)}
   389→                  className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-accent"
   390→                >
   391→                  {getTypeOptions().map(type => (
   392→                    <option key={type} value={type}>{type}</option>
   393→                  ))}
   394→                </select>
   395→

   396→
   397→

   398→                Content *
   399→                <textarea
   400→                  value={newItemContent}
   401→                  onChange={(e) => setNewItemContent(e.target.value)}
   402→                  rows={4}
   403→                  className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent resize-none"
   404→                  placeholder="Enter memory content..."
   405→                />
   406→

   407→

   408→
   409→

   410→              <Dialog.Close asChild>
   411→                <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
   412→                  Cancel
   413→                </button>
   414→              </Dialog.Close>
   415→              <button
   416→                onClick={handleAddItem}
   417→                disabled={isSaving || !newItemContent || (activeTab === 'infrastructure' && !newItemName)}
   418→                className="px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   419→              >
   420→                {isSaving ? 'Saving...' : 'Add Item'}
   421→              </button>
   422→

   423→          </Dialog.Content>
   424→        </Dialog.Portal>
   425→      </Dialog.Root>
   426→
   427→      {/* Delete Confirmation Dialog */}
   428→      <AlertDialog.Root open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
   429→        <AlertDialog.Portal>
   430→          <AlertDialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   431→          <AlertDialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">
   432→            <AlertDialog.Title className="text-xl font-semibold text-white">
   433→              Delete Memory Item
   434→            </AlertDialog.Title>
   435→            <AlertDialog.Description className="mt-3 text-slate-400">
   436→              Are you sure you want to delete this memory item? This action cannot be undone.
   437→            </AlertDialog.Description>
   438→

   439→              <AlertDialog.Cancel asChild>
   440→                <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
   441→                  Cancel
   442→                </button>
   443→              </AlertDialog.Cancel>
   444→              <AlertDialog.Action asChild>
   445→                <button
   446→                  onClick={handleDeleteConfirm}
   447→                  disabled={isDeleting}
   448→                  className="px-4 py-2 text-sm bg-destructive hover:bg-destructive/80 text-white rounded-lg transition-colors disabled:opacity-50"
   449→                >
   450→                  {isDeleting ? 'Deleting...' : 'Delete'}
   451→                </button>
   452→              </AlertDialog.Action>
   453→

   454→          </AlertDialog.Content>
   455→        </AlertDialog.Portal>
   456→      </AlertDialog.Root>
   457→

   458→  )
   459→}
   460→
   461→function MemoryCard({
   462→  id: _id,
   463→  type,
   464→  content,
   465→  createdAt,
   466→  usageCount,
   467→  onDelete,
   468→}: {
   469→  id: number
   470→  type: string
   471→  content: string
   472→  createdAt: string
   473→  usageCount?: number
   474→  onDelete: () => void
   475→}) {
   476→  return (
   477→

   478→

   479→

   480→

   481→
   482→              {type}
   483→
   484→            {usageCount !== undefined && (
   485→              Used {usageCount} times
   486→            )}
   487→

   488→
{content}

   489→

   490→            Created: {new Date(createdAt).toLocaleString()}
   491→

   492→

   493→        <button
   494→          onClick={onDelete}
   495→          className="p-2 text-slate-400 hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
   496→          title="Delete"
   497→        >
   498→          <Trash2 size={16} />
   499→        </button>
   500→

   501→

   502→  )
   503→}
   504→
   505→function InfrastructureCard({
   506→  id: _id,
   507→  name,
   508→  type,
   509→  config,
   510→  createdAt,
   511→  onDelete,
   512→}: {
   513→  id: number
   514→  name: string
   515→  type: string
   516→  config: Record<string, unknown>
   517→  createdAt: string
   518→  onDelete: () => void
   519→}) {
   520→  return (
   521→

   522→

   523→

   524→

   525→
{name}

   526→
   527→              {type}
   528→
   529→

   530→

   531→            {JSON.stringify(config, null, 2)}
   532→

   533→

   534→            Created: {new Date(createdAt).toLocaleString()}
   535→

   536→

   537→        <button
   538→          onClick={onDelete}
   539→          className="p-2 text-slate-400 hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
   540→          title="Delete"
   541→        >
   542→          <Trash2 size={16} />
   543→        </button>
   544→

   545→

   546→  )
   547→}
   548→
   549→function EmptyState({
   550→  title,
   551→  description,
   552→}: {
   553→  title: string
   554→  description: string
   555→}) {
   556→  return (
   557→

   558→      <Brain size={48} className="text-slate-600 mx-auto mb-4" />
   559→
{title}

   560→
{description}

   561→

   562→  )
   563→}
   564→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import { useState, useEffect } from 'react'
import { Brain, Globe, Server, Plus, Search, Trash2, X } from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'
import * as AlertDialog from '@radix-ui/react-alert-dialog'
import { useProjectStore } from '../stores/projectStore'

type MemoryTab = 'project' | 'global' | 'infrastructure'

interface ProjectMemoryItem {
  id: number
  project_id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  created_at: string
}

interface GlobalMemoryItem {
  id: number
  type: string
  content: string
  metadata: Record<string, unknown> | null
  usage_count: number
  created_at: string
}

interface InfrastructureItem {
  id: number
  name: string
  type: string
  config: Record<string, unknown>
  projects: number[] | null
  created_at: string
  updated_at: string
}

const API_BASE = 'http://localhost:8000/api/memory'

export default function MemoryManager() {
  const { currentProject } = useProjectStore()
  const [activeTab, setActiveTab] = useState<MemoryTab>('project')
  const [searchQuery, setSearchQuery] = useState('')

  // Data states
  const [projectMemory, setProjectMemory] = useState<ProjectMemoryItem[]>([])
  const [globalMemory, setGlobalMemory] = useState<GlobalMemoryItem[]>([])
  const [infrastructure, setInfrastructure] = useState<InfrastructureItem[]>([])
  const [isLoading, setIsLoading] = useState(false)

  // Dialog states
  const [showAddDialog, setShowAddDialog] = useState(false)
  const [newItemType, setNewItemType] = useState('')
  const [newItemContent, setNewItemContent] = useState('')
  const [newItemName, setNewItemName] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Delete dialog states
  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
  const [itemToDelete, setItemToDelete] = useState<{ id: number; type: MemoryTab } | null>(null)
  const [isDeleting, setIsDeleting] = useState(false)

  const tabs = [
    { id: 'project' as const, label: 'Project Memory', icon: Brain },
    { id: 'global' as const, label: 'Global Memory', icon: Globe },
    { id: 'infrastructure' as const, label: 'Infrastructure', icon: Server },
  ]

  // Fetch data based on active tab
  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true)
      try {
        if (activeTab === 'project' && currentProject) {
          const response = await fetch(`${API_BASE}/project/${currentProject.id}`)
          if (response.ok) {
            const data = await response.json()
            setProjectMemory(data)
          }
        } else if (activeTab === 'global') {
          const response = await fetch(`${API_BASE}/global`)
          if (response.ok) {
            const data = await response.json()
            setGlobalMemory(data)
          }
        } else if (activeTab === 'infrastructure') {
          const response = await fetch(`${API_BASE}/infrastructure`)
          if (response.ok) {
            const data = await response.json()
            setInfrastructure(data)
          }
        }
      } catch (error) {
        console.error('Failed to fetch memory items:', error)
      } finally {
        setIsLoading(false)
      }
    }
    fetchData()
  }, [activeTab, currentProject])

  const getTypeOptions = () => {
    switch (activeTab) {
      case 'project':
        return ['insight', 'pattern', 'gotcha', 'codebase_map']
      case 'global':
        return ['preference', 'pattern', 'solution']
      case 'infrastructure':
        return ['server', 'docker', 'database', 'deployment']
      default:
        return []
    }
  }

  const handleOpenAddDialog = () => {
    setNewItemType(getTypeOptions()[0] || '')
    setNewItemContent('')
    setNewItemName('')
    setShowAddDialog(true)
  }

  const handleAddItem = async () => {
    if (!newItemType || (!newItemContent && activeTab !== 'infrastructure')) return

    setIsSaving(true)
    try {
      let response: Response

      if (activeTab === 'project' && currentProject) {
        response = await fetch(`${API_BASE}/project/${currentProject.id}`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ type: newItemType, content: newItemContent }),
        })
        if (response.ok) {
          const newItem = await response.json()
          setProjectMemory([...projectMemory, newItem])
        }
      } else if (activeTab === 'global') {
        response = await fetch(`${API_BASE}/global`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ type: newItemType, content: newItemContent }),
        })
        if (response.ok) {
          const newItem = await response.json()
          setGlobalMemory([...globalMemory, newItem])
        }
      } else if (activeTab === 'infrastructure') {
        response = await fetch(`${API_BASE}/infrastructure`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            name: newItemName,
            type: newItemType,
            config: { content: newItemContent }
          }),
        })
        if (response.ok) {
          const newItem = await response.json()
          setInfrastructure([...infrastructure, newItem])
        }
      }

      setShowAddDialog(false)
    } catch (error) {
      console.error('Failed to add memory item:', error)
    } finally {
      setIsSaving(false)
    }
  }

  const handleDeleteClick = (id: number, type: MemoryTab) => {
    setItemToDelete({ id, type })
    setShowDeleteDialog(true)
  }

  const handleDeleteConfirm = async () => {
    if (!itemToDelete) return

    setIsDeleting(true)
    try {
      let endpoint: string

      if (itemToDelete.type === 'project' && currentProject) {
        endpoint = `${API_BASE}/project/${currentProject.id}/${itemToDelete.id}`
      } else if (itemToDelete.type === 'global') {
        endpoint = `${API_BASE}/global/${itemToDelete.id}`
      } else {
        endpoint = `${API_BASE}/infrastructure/${itemToDelete.id}`
      }

      const response = await fetch(endpoint, { method: 'DELETE' })

      if (response.ok || response.status === 204) {
        if (itemToDelete.type === 'project') {
          setProjectMemory(projectMemory.filter(item => item.id !== itemToDelete.id))
        } else if (itemToDelete.type === 'global') {
          setGlobalMemory(globalMemory.filter(item => item.id !== itemToDelete.id))
        } else {
          setInfrastructure(infrastructure.filter(item => item.id !== itemToDelete.id))
        }
      }

      setShowDeleteDialog(false)
      setItemToDelete(null)
    } catch (error) {
      console.error('Failed to delete memory item:', error)
    } finally {
      setIsDeleting(false)
    }
  }

  const filterItems = <T extends { content?: string; name?: string; type: string }>(items: T[]) => {
    if (!searchQuery) return items
    const query = searchQuery.toLowerCase()
    return items.filter(item =>
      item.content?.toLowerCase().includes(query) ||
      item.name?.toLowerCase().includes(query) ||
      item.type.toLowerCase().includes(query)
    )
  }

  const filteredProjectMemory = filterItems(projectMemory)
  const filteredGlobalMemory = filterItems(globalMemory)
  const filteredInfrastructure = filterItems(infrastructure)

  return (

      {/* Header */}

Memory Manager

        <button
          onClick={handleOpenAddDialog}
          className="btn-accent flex items-center gap-2"
        >
          <Plus size={18} />
          Add Memory Item
        </button>

      {/* Tabs */}

        {tabs.map((tab) => {
          const Icon = tab.icon
          return (
            <button
              key={tab.id}
              onClick={() => setActiveTab(tab.id)}
              className={`flex items-center gap-2 px-4 py-2 rounded-md transition-colors ${
                activeTab === tab.id
                  ? 'bg-primary-700 text-white'
                  : 'text-slate-400 hover:text-white'
              }`}
            >
              <Icon size={16} />
              {tab.label}
            </button>
          )
        })}

      {/* Search */}

        <Search
          size={18}
          className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400"
        />
        <input
          type="text"
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          placeholder="Search memory items..."
          className="w-full pl-10 pr-4 py-2 bg-slate-800 border border-slate-700 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent"
        />

      {/* Content */}

        {isLoading ? (

Loading...

        ) : (
          <>
            {activeTab === 'project' && (

                {filteredProjectMemory.length === 0 ? (
                  <EmptyState
                    title="No Project Memory"
                    description="Memory items from your current project will appear here."
                  />
                ) : (
                  filteredProjectMemory.map(item => (
                    <MemoryCard
                      key={item.id}
                      id={item.id}
                      type={item.type}
                      content={item.content}
                      createdAt={item.created_at}
                      onDelete={() => handleDeleteClick(item.id, 'project')}
                    />
                  ))
                )}

            )}

            {activeTab === 'global' && (

                {filteredGlobalMemory.length === 0 ? (
                  <EmptyState
                    title="No Global Memory"
                    description="Cross-project patterns and preferences will appear here."
                  />
                ) : (
                  filteredGlobalMemory.map(item => (
                    <MemoryCard
                      key={item.id}
                      id={item.id}
                      type={item.type}
                      content={item.content}
                      createdAt={item.created_at}
                      usageCount={item.usage_count}
                      onDelete={() => handleDeleteClick(item.id, 'global')}
                    />
                  ))
                )}

            )}

            {activeTab === 'infrastructure' && (

                {filteredInfrastructure.length === 0 ? (
                  <EmptyState
                    title="No Infrastructure Config"
                    description="Server and deployment configurations will appear here."
                  />
                ) : (
                  filteredInfrastructure.map(item => (
                    <InfrastructureCard
                      key={item.id}
                      id={item.id}
                      name={item.name}
                      type={item.type}
                      config={item.config}
                      createdAt={item.created_at}
                      onDelete={() => handleDeleteClick(item.id, 'infrastructure')}
                    />
                  ))
                )}

            )}
          </>
        )}

      {/* Add Memory Dialog */}
      <Dialog.Root open={showAddDialog} onOpenChange={setShowAddDialog}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">

              <Dialog.Title className="text-xl font-semibold text-white">
                Add {activeTab === 'project' ? 'Project' : activeTab === 'global' ? 'Global' : 'Infrastructure'} Memory
              </Dialog.Title>
              <Dialog.Close asChild>
                <button className="p-1 text-slate-400 hover:text-white hover:bg-slate-700 rounded transition-colors" aria-label="Close">
                  <X size={20} />
                </button>
              </Dialog.Close>

              {activeTab === 'infrastructure' && (

                  Name *
                  <input
                    type="text"
                    value={newItemName}
                    onChange={(e) => setNewItemName(e.target.value)}
                    className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent"
                    placeholder="Enter config name"
                  />

              )}

                Type *
                <select
                  value={newItemType}
                  onChange={(e) => setNewItemType(e.target.value)}
                  className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-accent"
                >
                  {getTypeOptions().map(type => (
                    <option key={type} value={type}>{type}</option>
                  ))}
                </select>

                Content *
                <textarea
                  value={newItemContent}
                  onChange={(e) => setNewItemContent(e.target.value)}
                  rows={4}
                  className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent resize-none"
                  placeholder="Enter memory content..."
                />

              <Dialog.Close asChild>
                <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
                  Cancel
                </button>
              </Dialog.Close>
              <button
                onClick={handleAddItem}
                disabled={isSaving || !newItemContent || (activeTab === 'infrastructure' && !newItemName)}
                className="px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSaving ? 'Saving...' : 'Add Item'}
              </button>

          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

      {/* Delete Confirmation Dialog */}
      <AlertDialog.Root open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
        <AlertDialog.Portal>
          <AlertDialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <AlertDialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-800 border border-slate-700 rounded-lg p-6 w-full max-w-md z-50 shadow-xl">
            <AlertDialog.Title className="text-xl font-semibold text-white">
              Delete Memory Item
            </AlertDialog.Title>
            <AlertDialog.Description className="mt-3 text-slate-400">
              Are you sure you want to delete this memory item? This action cannot be undone.
            </AlertDialog.Description>

              <AlertDialog.Cancel asChild>
                <button className="px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 rounded-lg transition-colors">
                  Cancel
                </button>
              </AlertDialog.Cancel>
              <AlertDialog.Action asChild>
                <button
                  onClick={handleDeleteConfirm}
                  disabled={isDeleting}
                  className="px-4 py-2 text-sm bg-destructive hover:bg-destructive/80 text-white rounded-lg transition-colors disabled:opacity-50"
                >
                  {isDeleting ? 'Deleting...' : 'Delete'}
                </button>
              </AlertDialog.Action>

          </AlertDialog.Content>
        </AlertDialog.Portal>
      </AlertDialog.Root>

  )
}

function MemoryCard({
  id: _id,
  type,
  content,
  createdAt,
  usageCount,
  onDelete,
}: {
  id: number
  type: string
  content: string
  createdAt: string
  usageCount?: number
  onDelete: () => void
}) {
  return (

              {type}

            {usageCount !== undefined && (
              Used {usageCount} times
            )}

{content}

            Created: {new Date(createdAt).toLocaleString()}

        <button
          onClick={onDelete}
          className="p-2 text-slate-400 hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
          title="Delete"
        >
          <Trash2 size={16} />
        </button>

  )
}

function InfrastructureCard({
  id: _id,
  name,
  type,
  config,
  createdAt,
  onDelete,
}: {
  id: number
  name: string
  type: string
  config: Record<string, unknown>
  createdAt: string
  onDelete: () => void
}) {
  return (

{name}

              {type}

            {JSON.stringify(config, null, 2)}

            Created: {new Date(createdAt).toLocaleString()}

        <button
          onClick={onDelete}
          className="p-2 text-slate-400 hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
          title="Delete"
        >
          <Trash2 size={16} />
        </button>

  )
}

function EmptyState({
  title,
  description,
}: {
  title: string
  description: string
}) {
  return (

      <Brain size={48} className="text-slate-600 mx-auto mb-4" />

{title}

{description}

  )
}


I can see that all the main forms already have submit button disable states during processing:

1. **KanbanBoard.tsx**:
   - Create Task: `isCreating` state, button shows "Creating..." when processing ✓
   - Edit Task: `isSaving` state, button shows "Saving..." when processing ✓
   - Delete Task: `isDeleting` state, button shows "Deleting..." when processing ✓

2. **Dashboard.tsx**:
   - Edit Project: `isSaving` state, button shows "Saving..." when processing ✓
   - Delete Project: `isDeleting` state, button shows "Deleting..." when processing ✓

3. **MemoryManager.tsx**:
   - Add Memory: `isSaving` state, button shows "Saving..." when processing ✓
   - Delete Memory: `isDeleting` state, button shows "Deleting..." when processing ✓

Now let me verify this through the UI by testing the Add Task form. I'll click the Create Task button and check if it shows "Creating..." and is disabled during submission:


### Page state
- Page URL: http://localhost:3000/kanban
- Page Title: Auto-Claude-Plus
- Page Snapshot:
```yaml
- generic:
  - generic:
    - generic:
      - complementary:
        - generic:
          - heading [level=1]: Auto-Claude-Plus
          - paragraph: Autonomous Coding Framework
        - generic:
          - generic:
            - generic: Projects
            - link:
              - /url: /new-project
              - img
          - generic:
            - button:
              - img
              - generic: MULTI_TAB_TEST_PROJECT_EDITED_IN_TAB_B
            - button:
              - img
              - generic: MODIFIED_PROJECT_NAME_FOR_ERROR_TEST
            - button:
              - img
              - generic: EMPTY_STATE_TEST_PROJECT
            - button:
              - img
              - generic: PERSIST_TEST_001
            - button:
              - img
              - generic: DESIGN_MODE_TEST_PROJECT
            - button:
              - img
              - generic: TEST_PROJECT_12345
            - button:
              - img
              - generic: TEST_PROJECT_67890
        - navigation:
          - list:
            - listitem:
              - link:
                - /url: /
                - img
                - generic: Dashboard
            - listitem:
              - link:
                - /url: /kanban
                - img
                - generic: Kanban Board
            - listitem:
              - link:
                - /url: /terminals
                - img
                - generic: Terminals
            - listitem:
              - link:
                - /url: /memory
                - img
                - generic: Memory
            - listitem:
              - link:
                - /url: /infrastructure
                - img
                - generic: Infrastructure
            - listitem:
              - link:
                - /url: /settings
                - img
                - generic: Settings
        - generic:
          - paragraph: v0.1.0
      - generic:
        - banner:
          - generic:
            - generic: PERSIST_TEST_001
            - img
            - generic: Phase 1 of 1
          - generic:
            - generic:
              - generic: "Progress:"
              - generic: 100%
          - generic:
            - button:
              - img
        - main:
          - generic:
            - generic:
              - heading [level=1]: Kanban Board
              - generic:
                - generic:
                  - img
                  - combobox
                - generic:
                  - img
                  - combobox
                - generic:
                  - button:
                    - img
                  - button:
                    - img
                - button [expanded]:
                  - img
                  - text: Add Task
            - generic:
              - generic:
                - generic:
                  - generic:
                    - generic:
                      - heading [level=2]: Backlog
                      - generic: "21"
                  - generic:
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: DOUBLE_CLICK_TEST_TASK
                          - generic:
                            - generic: Backlog
                            - generic: Low
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_16
                          - paragraph: Task 16 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Critical
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_15
                          - paragraph: Task 15 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: High
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_14
                          - paragraph: Task 14 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Medium
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_12
                          - paragraph: Task 12 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Critical
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_11
                          - paragraph: Task 11 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: High
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_10
                          - paragraph: Task 10 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Medium
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_09
                          - paragraph: Task 9 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Low
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_08
                          - paragraph: Task 8 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Critical
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_07
                          - paragraph: Task 7 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: High
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_06
                          - paragraph: Task 6 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Medium
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_05
                          - paragraph: Task 5 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Low
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_04
                          - paragraph: Task 4 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Critical
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_03
                          - paragraph: Task 3 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: High
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_02
                          - paragraph: Task 2 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Medium
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PAGINATION_TEST_01
                          - paragraph: Task 1 for pagination
                          - generic:
                            - generic: Backlog
                            - generic: Low
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: FILTER_TEST_LOW
                          - paragraph: Low priority task for filter test
                          - generic:
                            - generic: Backlog
                            - generic: Low
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: FILTER_TEST_MEDIUM
                          - paragraph: Medium priority task for filter test
                          - generic:
                            - generic: Backlog
                            - generic: Medium
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: FILTER_TEST_CRITICAL
                          - paragraph: Critical priority task for filter test
                          - generic:
                            - generic: Backlog
                            - generic: Critical
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: DROPDOWN_TEST_TASK
                          - generic:
                            - generic: Backlog
                            - generic: High
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: STATS_TEST_TASK_003
                          - paragraph: Test task 3 for dashboard statistics verification
                          - generic:
                            - generic: Backlog
                            - generic: Low
                - generic:
                  - generic:
                    - generic:
                      - heading [level=2]: In Progress
                      - generic: "1"
                  - generic:
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: PERSIST_TASK_001
                          - paragraph: Test task for persistence verification
                          - generic:
                            - generic: In Progress
                            - generic: Low
                - generic:
                  - generic:
                    - generic:
                      - heading [level=2]: QA
                      - generic: "0"
                  - generic:
                    - generic: No tasks
                - generic:
                  - generic:
                    - generic:
                      - heading [level=2]: Done
                      - generic: "3"
                  - generic:
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: STATS_TEST_TASK_002
                          - paragraph: Test task 2 for dashboard statistics verification
                          - generic:
                            - generic: Done
                            - generic: Low
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: STATS_TEST_TASK_001
                          - paragraph: Test task 1 for dashboard statistics verification
                          - generic:
                            - generic: Done
                            - generic: Low
                    - generic:
                      - generic:
                        - img
                        - generic:
                          - heading [level=3]: REAL_DATA_TASK_XYZ123_MODIFIED
                          - paragraph: "Unique description to verify real data: ABC_UNIQUE_789"
                          - generic:
                            - generic: Done
                            - generic: Low
                - generic:
                  - generic:
                    - generic:
                      - heading [level=2]: Blocked
                      - generic: "0"
                  - generic:
                    - generic: No tasks
        - contentinfo:
          - generic:
            - generic:
              - img
              - generic: "Agents:"
            - generic: None active
          - generic:
            - img
            - generic: Backend connected
  - dialog "Add New Task" [ref=e616]:
    - generic [ref=e617]:
      - heading "Add New Task" [level=2] [ref=e618]
      - button [ref=e619] [cursor=pointer]:
        - img [ref=e620]
    - paragraph [ref=e623]: Create a new task for this project.
    - generic [ref=e624]:
      - generic [ref=e625]:
        - generic [ref=e626]: Task Name *
        - textbox "Enter task name" [active] [ref=e627]: BUTTON_DISABLE_TEST
      - generic [ref=e628]:
        - generic [ref=e629]: Description
        - textbox "Enter task description" [ref=e630]
      - generic [ref=e631]:
        - generic [ref=e632]: Priority
        - combobox [ref=e633]:
          - option "Low" [selected]
          - option "Medium"
          - option "High"
          - option "Critical"
    - generic [ref=e634]:
      - button "Cancel" [ref=e635] [cursor=pointer]
      - button "Create Task" [ref=e636] [cursor=pointer]
```


The dialog is still open with "BUTTON_DISABLE_TEST" filled in. Now let me click the "Create Task" button and observe the behavior. Since the state change happens very fast, I need to verify the code implements this correctly. Looking at the code again:

```javascript
disabled={isCreating || !newTaskName.trim()}
...
{isCreating ? 'Creating...' : 'Create Task'}
```

This confirms:
1. Button is disabled when `isCreating` is true
2. Button text changes to "Creating..." when `isCreating` is true
3. Button re-enables when form completes (setIsCreating(false) in finally block)

Let me click the button and verify the task is created, then check the feature is working: