diff options
| author | soryu <soryu@soryu.co> | 2026-01-29 02:24:48 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-29 02:24:48 +0000 |
| commit | cfe3ea0aae878ae8f591acdc33a48332ac875b9e (patch) | |
| tree | 49a7f2d17f494f6c5f88d7c0692d57c21dea3244 | |
| parent | 764ace78046e78cce36b64cb3682cc5489bcf9d7 (diff) | |
| download | soryu-cfe3ea0aae878ae8f591acdc33a48332ac875b9e.tar.gz soryu-cfe3ea0aae878ae8f591acdc33a48332ac875b9e.zip | |
fix: Remove mistaken red team UI from VN frontend (#47)
* feat: Add Red Team UI to makima/frontend contract creation
- Add redTeamEnabled and redTeamPrompt state to contracts page
- Add "Enable Red Team Monitoring" checkbox with description
- Add conditional "Custom Review Criteria" textarea when enabled
- Include redTeamEnabled/redTeamPrompt in CreateContractRequest
- Reset red team fields when canceling contract creation
- Add redTeamEnabled to ContractSummary and Contract types
- Add redTeamEnabled/redTeamPrompt to CreateContractRequest type
- Add Red Team badge (đ) to ContractList for enabled contracts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: Remove mistaken red team UI from VN frontend
PR #39 accidentally added red team UI code to the wrong frontend directory
(frontend/ instead of makima/frontend/). The correct implementation is
already in makima/frontend/. This commit removes the mistaken changes:
- Delete ContractCreateModal.tsx (was added by mistake)
- Revert ContractList.tsx to remove red team badge and create modal
- Revert ContractDetail.tsx to remove red team tab and notifications
- Revert types.ts to remove contract/task types
- Revert pc98.css to remove red team styling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* [WIP] Heartbeat checkpoint - 2026-01-29 02:18:40 UTC
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
| -rw-r--r-- | frontend/src/components/ContractCreateModal.tsx | 185 | ||||
| -rw-r--r-- | frontend/src/components/ContractDetail.tsx | 139 | ||||
| -rw-r--r-- | frontend/src/components/ContractList.tsx | 61 | ||||
| -rw-r--r-- | frontend/src/styles/pc98.css | 644 | ||||
| -rw-r--r-- | frontend/src/types.ts | 95 | ||||
| -rw-r--r-- | frontend/tsconfig.tsbuildinfo | 2 |
6 files changed, 23 insertions, 1103 deletions
diff --git a/frontend/src/components/ContractCreateModal.tsx b/frontend/src/components/ContractCreateModal.tsx deleted file mode 100644 index e1d9732..0000000 --- a/frontend/src/components/ContractCreateModal.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import React, { useState } from 'react' - -interface ContractCreateModalProps { - isOpen: boolean - onClose: () => void - onCreated: () => void -} - -interface CreateContractForm { - name: string - description: string - contractType: string - redTeamEnabled: boolean - redTeamPrompt: string -} - -export function ContractCreateModal({ isOpen, onClose, onCreated }: ContractCreateModalProps) { - const [form, setForm] = useState<CreateContractForm>({ - name: '', - description: '', - contractType: 'simple', - redTeamEnabled: false, - redTeamPrompt: '', - }) - const [loading, setLoading] = useState(false) - const [error, setError] = useState<string | null>(null) - - if (!isOpen) return null - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault() - setLoading(true) - setError(null) - - try { - const response = await fetch('/api/v1/contracts', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - name: form.name, - description: form.description || undefined, - contract_type: form.contractType, - red_team_enabled: form.redTeamEnabled, - red_team_prompt: form.redTeamEnabled && form.redTeamPrompt ? form.redTeamPrompt : undefined, - }), - }) - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})) - throw new Error(errorData.message || `Failed to create contract: ${response.statusText}`) - } - - // Reset form and close modal - setForm({ - name: '', - description: '', - contractType: 'simple', - redTeamEnabled: false, - redTeamPrompt: '', - }) - onCreated() - onClose() - } catch (err) { - setError(err instanceof Error ? err.message : 'Unknown error') - } finally { - setLoading(false) - } - } - - return ( - <div className="modal-overlay" onClick={onClose}> - <div className="settings-modal contract-create-modal" onClick={(e) => e.stopPropagation()}> - <div className="modal-header"> - <h2 className="modal-title">Create Contract</h2> - <button className="modal-close-btn" onClick={onClose}> - à - </button> - </div> - - <form onSubmit={handleSubmit}> - <div className="modal-content"> - {error && ( - <div className="form-error"> - {error} - </div> - )} - - <div className="settings-section"> - <h3>Contract Details</h3> - - <div className="setting-item"> - <label> - Name - <input - type="text" - value={form.name} - onChange={(e) => setForm({ ...form, name: e.target.value })} - placeholder="Enter contract name" - required - className="form-input" - /> - </label> - </div> - - <div className="setting-item"> - <label> - Description - <textarea - value={form.description} - onChange={(e) => setForm({ ...form, description: e.target.value })} - placeholder="Enter contract description (optional)" - className="form-textarea" - rows={3} - /> - </label> - </div> - - <div className="setting-item"> - <label> - Contract Type - <select - value={form.contractType} - onChange={(e) => setForm({ ...form, contractType: e.target.value })} - className="form-select" - > - <option value="simple">Simple</option> - <option value="specification">Specification</option> - <option value="execute">Execute</option> - </select> - </label> - </div> - </div> - - <div className="settings-section"> - <h3>Red Team Monitoring</h3> - - <div className="setting-item"> - <label className="checkbox-label"> - <input - type="checkbox" - checked={form.redTeamEnabled} - onChange={(e) => setForm({ ...form, redTeamEnabled: e.target.checked })} - /> - <span>Enable Red Team monitoring</span> - </label> - <div className="setting-description"> - Spawns a parallel task that monitors work output for quality and compliance - </div> - </div> - - {form.redTeamEnabled && ( - <div className="setting-item red-team-prompt-container"> - <label> - Custom review criteria (optional) - <textarea - value={form.redTeamPrompt} - onChange={(e) => setForm({ ...form, redTeamPrompt: e.target.value })} - placeholder="Enter custom criteria for the red team to evaluate against... (e.g., 'Ensure all functions have proper error handling', 'Verify security best practices are followed')" - className="form-textarea" - rows={4} - /> - </label> - <div className="setting-description"> - Provide specific criteria for the red team to focus on during reviews - </div> - </div> - )} - </div> - </div> - - <div className="modal-footer"> - <button type="button" className="modal-btn secondary" onClick={onClose} disabled={loading}> - Cancel - </button> - <button type="submit" className="modal-btn primary" disabled={loading || !form.name.trim()}> - {loading ? 'Creating...' : 'Create Contract'} - </button> - </div> - </form> - </div> - </div> - ) -} diff --git a/frontend/src/components/ContractDetail.tsx b/frontend/src/components/ContractDetail.tsx index a9dd550..72527ce 100644 --- a/frontend/src/components/ContractDetail.tsx +++ b/frontend/src/components/ContractDetail.tsx @@ -12,8 +12,6 @@ interface TaskSummary { id: string name: string status: string - is_supervisor?: boolean - is_red_team?: boolean } interface ContractRepository { @@ -32,24 +30,6 @@ interface Contract { status: string version: number created_at: string - red_team_enabled?: boolean - red_team_prompt?: string -} - -interface RedTeamNotification { - id: string - contract_id: string - red_team_task_id: string - related_task_id?: string - message: string - severity: 'info' | 'warning' | 'critical' - file_path?: string - context?: string - delivered: boolean - delivered_at?: string - acknowledged: boolean - acknowledged_at?: string - created_at: string } interface ContractWithRelations { @@ -59,7 +39,7 @@ interface ContractWithRelations { tasks: TaskSummary[] } -type Tab = 'overview' | 'files' | 'tasks' | 'repositories' | 'red-team' +type Tab = 'overview' | 'files' | 'tasks' | 'repositories' export function ContractDetail() { const { id } = useParams<{ id: string }>() @@ -67,8 +47,6 @@ export function ContractDetail() { const [loading, setLoading] = useState(true) const [error, setError] = useState<string | null>(null) const [activeTab, setActiveTab] = useState<Tab>('overview') - const [notifications, setNotifications] = useState<RedTeamNotification[]>([]) - const [notificationsLoading, setNotificationsLoading] = useState(false) useEffect(() => { async function fetchContract() { @@ -92,28 +70,6 @@ export function ContractDetail() { fetchContract() }, [id]) - // Fetch red team notifications when viewing red-team tab - useEffect(() => { - async function fetchNotifications() { - if (!id || activeTab !== 'red-team' || !data?.contract.red_team_enabled) return - - try { - setNotificationsLoading(true) - const response = await fetch(`/api/v1/contracts/${id}/red-team/notifications`) - if (response.ok) { - const notificationData = await response.json() - setNotifications(notificationData.notifications || []) - } - } catch (err) { - console.error('Failed to fetch red team notifications:', err) - } finally { - setNotificationsLoading(false) - } - } - - fetchNotifications() - }, [id, activeTab, data?.contract.red_team_enabled]) - if (loading) { return ( <div className="contract-detail-container"> @@ -152,14 +108,7 @@ export function ContractDetail() { <Link to="/contracts" className="back-link"> Back to Contracts </Link> - <h1 className="contract-title"> - {contract.name} - {contract.red_team_enabled && ( - <span className="red-team-badge" title="Red Team monitoring enabled"> - đĄī¸ Red Team - </span> - )} - </h1> + <h1 className="contract-title">{contract.name}</h1> {contract.description && ( <p className="contract-description">{contract.description}</p> )} @@ -195,14 +144,6 @@ export function ContractDetail() { > Repositories ({repositories.length}) </button> - {contract.red_team_enabled && ( - <button - className={`tab-button red-team-tab ${activeTab === 'red-team' ? 'active' : ''}`} - onClick={() => setActiveTab('red-team')} - > - đĄī¸ Red Team - </button> - )} </div> <div className="contract-tab-content"> @@ -253,12 +194,8 @@ export function ContractDetail() { ) : ( <ul className="task-list"> {tasks.map((task) => ( - <li key={task.id} className={`task-item ${task.is_red_team ? 'red-team-task' : ''}`}> - <h3> - {task.is_red_team && <span className="task-badge red-team">đĄī¸</span>} - {task.is_supervisor && <span className="task-badge supervisor">đ</span>} - {task.name} - </h3> + <li key={task.id} className="task-item"> + <h3>{task.name}</h3> <span className={`task-status status-${task.status}`}> {task.status} </span> @@ -289,74 +226,6 @@ export function ContractDetail() { )} </div> )} - - {activeTab === 'red-team' && contract.red_team_enabled && ( - <div className="tab-panel red-team-panel"> - <h2>đĄī¸ Red Team Monitoring</h2> - - {contract.red_team_prompt && ( - <div className="red-team-prompt"> - <h3>Review Criteria</h3> - <p>{contract.red_team_prompt}</p> - </div> - )} - - <div className="red-team-status"> - <h3>Red Team Task</h3> - {(() => { - const redTeamTask = tasks.find(t => t.is_red_team) - if (redTeamTask) { - return ( - <div className="red-team-task-info"> - <span className="task-name">{redTeamTask.name}</span> - <span className={`task-status status-${redTeamTask.status}`}> - {redTeamTask.status} - </span> - </div> - ) - } - return <p className="no-task">Red team task not yet spawned</p> - })()} - </div> - - <div className="red-team-notifications"> - <h3>Alerts ({notifications.length})</h3> - {notificationsLoading ? ( - <p>Loading notifications...</p> - ) : notifications.length === 0 ? ( - <p className="no-alerts">No alerts from red team</p> - ) : ( - <ul className="notification-list"> - {notifications.map((notification) => ( - <li - key={notification.id} - className={`notification-item severity-${notification.severity}`} - > - <div className="notification-header"> - <span className={`severity-badge ${notification.severity}`}> - {notification.severity === 'critical' && 'đ¨'} - {notification.severity === 'warning' && 'â ī¸'} - {notification.severity === 'info' && 'âšī¸'} - {notification.severity.toUpperCase()} - </span> - <span className="notification-time"> - {new Date(notification.created_at).toLocaleString()} - </span> - </div> - <p className="notification-message">{notification.message}</p> - {notification.file_path && ( - <span className="notification-file">File: {notification.file_path}</span> - )} - {notification.context && ( - <pre className="notification-context">{notification.context}</pre> - )} - </li> - ))} - </ul> - )} - </div> - </div> - )} </div> </div> ) diff --git a/frontend/src/components/ContractList.tsx b/frontend/src/components/ContractList.tsx index 253b44f..77012db 100644 --- a/frontend/src/components/ContractList.tsx +++ b/frontend/src/components/ContractList.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState, useCallback } from 'react' +import React, { useEffect, useState } from 'react' import { Link } from 'react-router-dom' -import { ContractCreateModal } from './ContractCreateModal' interface ContractSummary { id: string @@ -13,35 +12,32 @@ interface ContractSummary { task_count: number repository_count: number created_at: string - // Red team fields - red_team_enabled?: boolean } export function ContractList() { const [contracts, setContracts] = useState<ContractSummary[]>([]) const [loading, setLoading] = useState(true) const [error, setError] = useState<string | null>(null) - const [showCreateModal, setShowCreateModal] = useState(false) - const fetchContracts = useCallback(async () => { - try { - setLoading(true) - const response = await fetch('/api/v1/contracts') - if (!response.ok) { - throw new Error(`Failed to fetch contracts: ${response.statusText}`) + useEffect(() => { + async function fetchContracts() { + try { + setLoading(true) + const response = await fetch('/api/v1/contracts') + if (!response.ok) { + throw new Error(`Failed to fetch contracts: ${response.statusText}`) + } + const data = await response.json() + setContracts(data.contracts || []) + } catch (err) { + setError(err instanceof Error ? err.message : 'Unknown error') + } finally { + setLoading(false) } - const data = await response.json() - setContracts(data.contracts || []) - } catch (err) { - setError(err instanceof Error ? err.message : 'Unknown error') - } finally { - setLoading(false) } - }, []) - useEffect(() => { fetchContracts() - }, [fetchContracts]) + }, []) if (loading) { return ( @@ -61,15 +57,7 @@ export function ContractList() { return ( <div className="contract-list-container"> - <div className="contract-list-header"> - <h1>Contracts</h1> - <button - className="create-contract-btn" - onClick={() => setShowCreateModal(true)} - > - + New Contract - </button> - </div> + <h1>Contracts</h1> {contracts.length === 0 ? ( <p>No contracts found</p> ) : ( @@ -77,14 +65,7 @@ export function ContractList() { {contracts.map((contract) => ( <li key={contract.id} className="contract-item"> <Link to={`/contracts/${contract.id}`}> - <h2> - {contract.name} - {contract.red_team_enabled && ( - <span className="red-team-badge" title="Red Team monitoring enabled"> - đ - </span> - )} - </h2> + <h2>{contract.name}</h2> {contract.description && <p>{contract.description}</p>} <div className="contract-meta"> <span>Phase: {contract.phase}</span> @@ -97,12 +78,6 @@ export function ContractList() { ))} </ul> )} - - <ContractCreateModal - isOpen={showCreateModal} - onClose={() => setShowCreateModal(false)} - onCreated={fetchContracts} - /> </div> ) } diff --git a/frontend/src/styles/pc98.css b/frontend/src/styles/pc98.css index a420115..4dcf15e 100644 --- a/frontend/src/styles/pc98.css +++ b/frontend/src/styles/pc98.css @@ -4621,647 +4621,3 @@ button:focus-visible { display: none; } } - -/* ============================================================================= - Contract List & Detail Styles - ============================================================================= */ - -.contract-list-container, -.contract-detail-container { - padding: 20px; - max-width: 1200px; - margin: 0 auto; - font-family: 'MS Gothic', monospace; - color: #ffffff; -} - -.contract-list-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; -} - -.contract-list-header h1 { - font-size: 24px; - color: #66ccff; - margin: 0; - text-transform: uppercase; - letter-spacing: 1px; -} - -.create-contract-btn { - appearance: none; - background: linear-gradient(180deg, #004466, #002233); - border: 2px solid #66ccff; - color: #ffffff; - font-family: 'MS Gothic', monospace; - font-size: 13px; - font-weight: bold; - padding: 8px 16px; - cursor: pointer; - border-radius: 4px; - transition: all 0.2s ease; -} - -.create-contract-btn:hover { - background: linear-gradient(180deg, #005577, #003344); - box-shadow: 0 0 10px rgba(102, 204, 255, 0.4); -} - -.contract-list { - list-style: none; - padding: 0; - margin: 0; -} - -.contract-item { - margin-bottom: 15px; - border: 1px solid rgba(102, 204, 255, 0.3); - background: rgba(0, 0, 0, 0.5); - transition: all 0.3s ease; -} - -.contract-item:hover { - border-color: #66ccff; - background: rgba(102, 204, 255, 0.05); -} - -.contract-item a { - display: block; - padding: 15px; - text-decoration: none; - color: inherit; -} - -.contract-item h2 { - font-size: 16px; - color: #ffffff; - margin: 0 0 8px 0; - display: flex; - align-items: center; - gap: 10px; -} - -.contract-item p { - font-size: 13px; - color: rgba(255, 255, 255, 0.7); - margin: 0 0 10px 0; -} - -.contract-meta { - display: flex; - flex-wrap: wrap; - gap: 15px; - font-size: 12px; - color: rgba(102, 204, 255, 0.8); -} - -/* ============================================================================= - Red Team Styling - ============================================================================= */ - -/* Red Team Badge - Contract List and Detail */ -.red-team-badge { - display: inline-flex; - align-items: center; - gap: 4px; - margin-left: 8px; - padding: 2px 8px; - font-size: 12px; - font-weight: normal; - background: linear-gradient(180deg, #4a0000, #2d0000); - border: 1px solid #ff4444; - border-radius: 4px; - color: #ff6666; - vertical-align: middle; - box-shadow: 0 0 6px rgba(255, 68, 68, 0.3); -} - -/* Contract Detail Header */ -.contract-detail-header { - margin-bottom: 20px; -} - -.back-link { - display: inline-block; - font-size: 12px; - color: #66ccff; - text-decoration: none; - margin-bottom: 15px; - transition: opacity 0.3s ease; -} - -.back-link:hover { - opacity: 0.8; -} - -.contract-title { - display: flex; - align-items: center; - gap: 15px; - flex-wrap: wrap; - font-size: 24px; - color: #66ccff; - margin: 0 0 10px 0; -} - -.contract-description { - font-size: 14px; - color: rgba(255, 255, 255, 0.7); - margin: 10px 0; -} - -/* Contract Tabs */ -.contract-tabs { - display: flex; - flex-wrap: wrap; - gap: 5px; - margin-bottom: 20px; - border-bottom: 1px solid rgba(102, 204, 255, 0.3); - padding-bottom: 10px; -} - -.tab-button { - font-family: 'MS Gothic', monospace; - font-size: 12px; - padding: 8px 16px; - border: 1px solid rgba(102, 204, 255, 0.3); - background: rgba(0, 0, 0, 0.3); - color: rgba(255, 255, 255, 0.7); - cursor: pointer; - transition: all 0.3s ease; -} - -.tab-button:hover { - border-color: #66ccff; - color: #ffffff; -} - -.tab-button.active { - background: rgba(102, 204, 255, 0.15); - border-color: #66ccff; - color: #66ccff; -} - -/* Red Team Tab Button */ -.tab-button.red-team-tab { - background: linear-gradient(180deg, #3d0000, #1a0000); - border-color: #ff4444; - color: #ff6666; -} - -.tab-button.red-team-tab:hover { - background: linear-gradient(180deg, #4a0000, #2d0000); - box-shadow: 0 0 8px rgba(255, 68, 68, 0.4); -} - -.tab-button.red-team-tab.active { - background: linear-gradient(180deg, #5c0000, #3d0000); - border-color: #ff6666; - color: #ffffff; - box-shadow: 0 0 12px rgba(255, 68, 68, 0.5); -} - -/* Tab Content */ -.tab-panel { - padding: 20px; - background: rgba(0, 0, 0, 0.3); - border: 1px solid rgba(102, 204, 255, 0.2); -} - -.tab-panel h2 { - font-size: 18px; - color: #66ccff; - margin: 0 0 15px 0; - text-transform: uppercase; - letter-spacing: 1px; -} - -.overview-list { - display: grid; - grid-template-columns: 120px 1fr; - gap: 10px; -} - -.overview-list dt { - color: rgba(255, 255, 255, 0.6); - font-size: 13px; -} - -.overview-list dd { - color: #ffffff; - margin: 0; - font-size: 13px; -} - -/* File/Task/Repository Lists */ -.file-list, -.task-list, -.repository-list { - list-style: none; - padding: 0; - margin: 0; -} - -.file-item, -.task-item, -.repository-item { - padding: 12px; - margin-bottom: 10px; - border: 1px solid rgba(102, 204, 255, 0.2); - background: rgba(0, 0, 0, 0.3); - transition: all 0.3s ease; -} - -.file-item:hover, -.task-item:hover, -.repository-item:hover { - border-color: rgba(102, 204, 255, 0.4); -} - -.file-item a { - text-decoration: none; - color: inherit; -} - -.file-item h3, -.task-item h3, -.repository-item h3 { - font-size: 14px; - color: #ffffff; - margin: 0 0 5px 0; - display: flex; - align-items: center; - gap: 8px; -} - -.file-phase { - font-size: 11px; - color: rgba(102, 204, 255, 0.7); -} - -.task-status { - font-size: 11px; - padding: 2px 8px; - border-radius: 2px; -} - -.task-status.status-pending { - background: rgba(255, 255, 0, 0.15); - color: #ffff00; - border: 1px solid rgba(255, 255, 0, 0.3); -} - -.task-status.status-active, -.task-status.status-running { - background: rgba(0, 255, 0, 0.15); - color: #00ff00; - border: 1px solid rgba(0, 255, 0, 0.3); -} - -.task-status.status-completed { - background: rgba(102, 204, 255, 0.15); - color: #66ccff; - border: 1px solid rgba(102, 204, 255, 0.3); -} - -.task-status.status-failed { - background: rgba(255, 100, 100, 0.15); - color: #ff6464; - border: 1px solid rgba(255, 100, 100, 0.3); -} - -/* Task Badges */ -.task-badge { - margin-right: 6px; - font-size: 14px; -} - -.task-badge.red-team { - color: #ff6666; -} - -.task-badge.supervisor { - color: #66ccff; -} - -.task-item.red-team-task { - border-left: 3px solid #ff4444; -} - -.primary-badge { - font-size: 10px; - padding: 2px 6px; - background: rgba(102, 204, 255, 0.15); - color: #66ccff; - border: 1px solid rgba(102, 204, 255, 0.3); - margin-left: 8px; -} - -.repo-type { - font-size: 11px; - color: rgba(255, 255, 255, 0.6); -} - -/* Red Team Panel */ -.red-team-panel { - background: linear-gradient(180deg, rgba(60, 0, 0, 0.3), rgba(30, 0, 0, 0.3)); - border-left: 3px solid #ff4444; -} - -.red-team-panel h2 { - color: #ff6666; - border-bottom: 2px solid #ff4444; - padding-bottom: 8px; -} - -.red-team-panel h3 { - color: #ffaaaa; - margin-top: 20px; - margin-bottom: 12px; -} - -/* Red Team Prompt Section */ -.red-team-prompt { - background: rgba(0, 0, 0, 0.4); - border: 1px solid #ff4444; - border-radius: 6px; - padding: 12px 16px; - margin-bottom: 16px; -} - -.red-team-prompt h3 { - margin-top: 0; - font-size: 14px; -} - -.red-team-prompt p { - margin: 0; - color: #cccccc; - font-style: italic; -} - -/* Red Team Status */ -.red-team-status { - margin-bottom: 20px; -} - -.red-team-task-info { - display: flex; - align-items: center; - justify-content: space-between; - padding: 12px; - background: rgba(0, 0, 0, 0.3); - border: 1px solid #444; - border-radius: 4px; -} - -.red-team-task-info .task-name { - font-weight: bold; - color: #ffffff; -} - -.no-task, .no-alerts { - color: #888888; - font-style: italic; -} - -/* Red Team Notifications */ -.red-team-notifications { - margin-top: 20px; -} - -.notification-list { - list-style: none; - padding: 0; - margin: 0; -} - -.notification-item { - padding: 12px 16px; - margin-bottom: 12px; - background: rgba(0, 0, 0, 0.4); - border-radius: 6px; - border-left: 4px solid; -} - -.notification-item.severity-info { - border-left-color: #66ccff; - background: linear-gradient(90deg, rgba(0, 80, 150, 0.2), transparent); -} - -.notification-item.severity-warning { - border-left-color: #ffcc00; - background: linear-gradient(90deg, rgba(150, 120, 0, 0.2), transparent); -} - -.notification-item.severity-critical { - border-left-color: #ff4444; - background: linear-gradient(90deg, rgba(150, 0, 0, 0.2), transparent); -} - -.notification-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 8px; -} - -.severity-badge { - padding: 2px 8px; - border-radius: 4px; - font-size: 11px; - font-weight: bold; - letter-spacing: 0.5px; -} - -.severity-badge.info { - background: #003366; - color: #66ccff; - border: 1px solid #66ccff; -} - -.severity-badge.warning { - background: #333300; - color: #ffcc00; - border: 1px solid #ffcc00; -} - -.severity-badge.critical { - background: #660000; - color: #ff4444; - border: 1px solid #ff4444; - animation: pulse-critical 2s infinite; -} - -@keyframes pulse-critical { - 0%, 100% { - box-shadow: 0 0 4px rgba(255, 68, 68, 0.5); - } - 50% { - box-shadow: 0 0 12px rgba(255, 68, 68, 0.8); - } -} - -.notification-time { - font-size: 11px; - color: #888888; -} - -.notification-message { - margin: 0 0 8px 0; - color: #ffffff; - line-height: 1.5; -} - -.notification-file { - display: block; - font-size: 12px; - color: #66ccff; - margin-bottom: 8px; -} - -.notification-context { - margin: 8px 0 0 0; - padding: 8px 12px; - background: rgba(0, 0, 0, 0.5); - border-radius: 4px; - font-size: 12px; - font-family: 'MS Gothic', monospace; - color: #aaaaaa; - white-space: pre-wrap; - overflow-x: auto; -} - -/* ============================================================================= - Contract Create Modal Styles - ============================================================================= */ - -.contract-create-modal { - max-width: 600px; -} - -.contract-create-modal .settings-section:last-child { - border-top: 1px solid #444; - padding-top: 16px; - margin-top: 8px; -} - -.form-input, -.form-textarea, -.form-select { - width: 100%; - padding: 8px 12px; - margin-top: 6px; - background: rgba(0, 0, 0, 0.4); - border: 1px solid #444; - border-radius: 4px; - color: #ffffff; - font-family: 'MS Gothic', monospace; - font-size: 13px; -} - -.form-input:focus, -.form-textarea:focus, -.form-select:focus { - outline: none; - border-color: #66ccff; - box-shadow: 0 0 6px rgba(102, 204, 255, 0.3); -} - -.form-textarea { - resize: vertical; - min-height: 80px; -} - -.form-select { - cursor: pointer; -} - -.form-select option { - background: #000000; - color: #ffffff; -} - -.form-error { - padding: 10px 14px; - margin-bottom: 16px; - background: rgba(255, 0, 0, 0.15); - border: 1px solid #ff4444; - border-radius: 4px; - color: #ff6666; - font-size: 13px; -} - -.checkbox-label { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; -} - -.checkbox-label span { - color: #ffffff; -} - -.setting-description { - margin-top: 4px; - font-size: 11px; - color: #888888; - padding-left: 24px; -} - -.red-team-prompt-container { - margin-top: 12px; - padding-left: 20px; -} - -.red-team-prompt-container textarea { - background: rgba(60, 0, 0, 0.2); - border-color: #ff4444; -} - -.red-team-prompt-container textarea:focus { - border-color: #ff6666; - box-shadow: 0 0 8px rgba(255, 68, 68, 0.3); -} - -.modal-btn.primary { - background: linear-gradient(180deg, #004466, #002233); - border-color: #66ccff; - color: #ffffff; -} - -.modal-btn.primary:hover { - background: linear-gradient(180deg, #005577, #003344); - box-shadow: 0 0 8px rgba(102, 204, 255, 0.4); -} - -.modal-btn.primary:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.modal-btn.secondary { - background: linear-gradient(180deg, #333333, #1a1a1a); - border-color: #666666; - color: #cccccc; -} - -.modal-btn.secondary:hover { - background: linear-gradient(180deg, #444444, #2a2a2a); -} - -.loading, -.error, -.not-found { - padding: 40px; - text-align: center; - font-size: 14px; - color: rgba(255, 255, 255, 0.7); -} - -.error { - color: #ff6464; -} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index ac8d417..c6d1263 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -9,98 +9,3 @@ export type Choice = { id: string label: string } - -// Contract types -export type ContractType = 'simple' | 'specification' | 'execute' -export type ContractPhase = 'research' | 'specify' | 'plan' | 'execute' | 'review' -export type ContractStatus = 'active' | 'completed' | 'archived' - -export interface ContractSummary { - id: string - name: string - description?: string - contractType: string - phase: string - status: string - supervisorTaskId?: string - localOnly: boolean - fileCount: number - taskCount: number - repositoryCount: number - version: number - createdAt: string - // Red team fields - redTeamEnabled?: boolean -} - -export interface Contract { - id: string - ownerId: string - name: string - description?: string - contractType: string - phase: string - status: string - supervisorTaskId?: string - autonomousLoop: boolean - phaseGuard: boolean - completedDeliverables: Record<string, string[]> - localOnly: boolean - redTeamEnabled: boolean - redTeamPrompt?: string - version: number - createdAt: string - updatedAt: string -} - -export interface CreateContractRequest { - name: string - description?: string - contractType?: string - initialPhase?: string - autonomousLoop?: boolean - phaseGuard?: boolean - localOnly?: boolean - redTeamEnabled?: boolean - redTeamPrompt?: string -} - -export interface TaskSummary { - id: string - contractId?: string - contractName?: string - contractPhase?: string - contractStatus?: string - parentTaskId?: string - depth: number - name: string - status: string - priority: number - progressSummary?: string - subtaskCount: number - version: number - isSupervisor: boolean - isRedTeam: boolean - hidden: boolean - createdAt: string - updatedAt: string -} - -// Red team notification types -export type NotificationSeverity = 'info' | 'warning' | 'critical' - -export interface RedTeamNotification { - id: string - contractId: string - redTeamTaskId: string - relatedTaskId?: string - message: string - severity: NotificationSeverity - filePath?: string - context?: string - delivered: boolean - deliveredAt?: string - acknowledged: boolean - acknowledgedAt?: string - createdAt: string -} diff --git a/frontend/tsconfig.tsbuildinfo b/frontend/tsconfig.tsbuildinfo index 0fd5af9..79408dc 100644 --- a/frontend/tsconfig.tsbuildinfo +++ b/frontend/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/app.tsx","./src/main.tsx","./src/types.ts","./src/components/bottombar.tsx","./src/components/choicemenu.tsx","./src/components/cityscapebackground.tsx","./src/components/configmodal.tsx","./src/components/contractcreatemodal.tsx","./src/components/contractdetail.tsx","./src/components/contractlist.tsx","./src/components/dialoguebox.tsx","./src/components/filedetail.tsx","./src/components/heartlogo.tsx","./src/components/landingpage.tsx","./src/components/loadingscreen.tsx","./src/components/origamidragonlogo.tsx","./src/components/topbar.tsx","./src/components/vnapp.tsx","./src/components/vninterface.tsx","./src/components/vnviewport.tsx","./src/services/ws.ts","./src/stores/index.ts"],"version":"5.9.2"}
\ No newline at end of file +{"root":["./src/app.tsx","./src/main.tsx","./src/types.ts","./src/components/bottombar.tsx","./src/components/choicemenu.tsx","./src/components/cityscapebackground.tsx","./src/components/configmodal.tsx","./src/components/contractdetail.tsx","./src/components/contractlist.tsx","./src/components/dialoguebox.tsx","./src/components/filedetail.tsx","./src/components/heartlogo.tsx","./src/components/landingpage.tsx","./src/components/loadingscreen.tsx","./src/components/origamidragonlogo.tsx","./src/components/topbar.tsx","./src/components/vnapp.tsx","./src/components/vninterface.tsx","./src/components/vnviewport.tsx","./src/services/ws.ts","./src/stores/index.ts"],"version":"5.9.2"}
\ No newline at end of file |
