75869f7e22
* auto-claude: subtask-0a-1 - Install Vercel AI SDK v6 core + all provider packages Added dependencies: ai@^6, @ai-sdk/anthropic, @ai-sdk/openai, @ai-sdk/google, @ai-sdk/amazon-bedrock, @ai-sdk/azure, @ai-sdk/mistral, @ai-sdk/groq, @ai-sdk/xai, @ai-sdk/openai-compatible, @ai-sdk/mcp, @modelcontextprotocol/sdk. Verified zod/v3 compat works with existing zod v4. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0b-1 - Create provider types and config interfaces Define SupportedProvider enum, ProviderConfig, ModelResolution, and ProviderCapabilities types. Port MODEL_ID_MAP, THINKING_BUDGET_MAP, MODEL_BETAS_MAP, and phase config types from phase_config.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0b-2 - Create provider factory: createProvider(config) → LanguageModel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0b-3 - Create provider registry using createProviderRegistry Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0b-4 - Create per-provider transforms layer Port thinking token normalization, tool ID format transforms, prompt caching thresholds, and adaptive thinking support from phase_config.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0c-1 - Port command-parser.ts from Python security/parser Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0c-2 - Port bash-validator.ts from Python security/hooks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0c-3 - Create path-containment.ts for filesystem boundary Add path-containment.ts with assertPathContained() for filesystem boundary enforcement including symlink resolution, traversal prevention, and cross-platform normalization. Add security-profile.ts for loading and caching project security profiles from .auto-claude config files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0c-4 - Write comprehensive Vitest tests for the security layer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0d-1 - Create tool types and Tool.define() wrapper Define ToolContext interface (cwd, projectDir, specDir, securityProfile), ToolPermission types, ToolExecutionOptions, and ToolDefinitionConfig. Create Tool.define() that wraps AI SDK v6 tool() with Zod v3 inputSchema and security hooks integration (bash validator pre-execution check). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0d-2 - Create 4 filesystem tools (Read, Write, Edit, Glob) Implements Read (line offset/limit, image base64, PDF support), Write (content validation, mkdir -p), Edit (exact string replacement, replace_all), and Glob (fs.globSync, mtime sort) with Zod schemas and path-containment security integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0d-3 - Create Bash, Grep, WebFetch, WebSearch tools Add the 4 remaining built-in tools following the existing Tool.define() pattern: - Bash: command execution with bashSecurityHook() integration, timeout, background support - Grep: ripgrep-based search with output modes, file type/glob filtering - WebFetch: URL fetching with timeout and content truncation - WebSearch: web search with domain allow/block list filtering Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0d-4 - Create ToolRegistry class with agent config registry Port tool constants (BASE_READ_TOOLS, BASE_WRITE_TOOLS, WEB_TOOLS), MCP tool lists, and AGENT_CONFIGS from Python models.py. Implement ToolRegistry with registerTool(), getToolsForAgent(), and helper functions getAgentConfig(), getDefaultThinkingLevel(), getRequiredMcpServers(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0e-1 - Port AGENT_CONFIGS from models.py to agent-configs.ts Port all 27 agent type configurations from Python backend to TypeScript. Includes tool lists, MCP server mappings, auto-claude tools, thinking defaults, and helper functions (getAgentConfig, getRequiredMcpServers, getDefaultThinkingLevel, mapMcpServerName). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0e-2 - Port phase-config.ts from phase_config.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0e-3 - Create auth resolver with multi-stage fallback chain Add auth types and resolver that reuses existing claude-profile/credential-utils.ts. Implements 4-stage fallback: profile OAuth token → profile API key → environment variable → default provider credentials. Supports all providers with provider-specific env var mappings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0e-4 - Create MCP client and registry Add MCP integration layer using @ai-sdk/mcp with @modelcontextprotocol/sdk for stdio/StreamableHTTP transports. Define server configs for context7, linear, graphiti, electron, puppeteer, auto-claude. Implement getMcpServersForAgent() via createMcpClientsForAgent() with dynamic server resolution and graceful fallback on connection failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0f-1 - Unit tests for provider factory, registry, and transforms Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-0f-2 - Unit tests for agent configs, phase config, and tool registry Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-1-1 - Create session types and client factory Add SessionConfig, SessionResult, StreamEvent, ProgressState types for the agent session runtime. Add AgentClientConfig/Result and SimpleClientConfig/Result types for the client layer. Implement createAgentClient() with full tool/MCP setup and createSimpleClient() for utility runners with minimal tools. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-1-1 - Fix unused imports in client factory Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-1-2 - Create stream handler and error classifier Add stream-handler.ts to process AI SDK v6 fullStream events (text-delta, reasoning, tool-call, tool-result, step-finish, error) and emit structured StreamEvents. Add error-classifier.ts ported from Python core/error_utils.py with classification for rate limit (429), auth failure (401), concurrency (400), tool execution, and abort errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-1-3 - Create progress-tracker.ts for phase detection from tool calls + text patterns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-1-4 - Create the core session runner: runAgentSession(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-1-5 - Write unit tests for session runtime Add 78 tests across 4 test files covering: - stream-handler: text-delta, reasoning, tool-call/result, step-finish, error, multi-step conversations - error-classifier: 429/401/400 detection, abort errors, classification priority, sanitization - progress-tracker: phase detection from tools/text, regression prevention, terminal locking - runner: completion, max_steps, auth retry, cancellation, event forwarding, tool tracking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-2-1 - Create AgentExecutor, worker thread, and worker bridge Add the worker thread infrastructure for running AI agent sessions off the main Electron thread: - executor.ts: AgentExecutor class wrapping WorkerBridge with start/stop/retry - worker.ts: Worker thread entry point receiving config via workerData, running runAgentSession(), posting structured messages back via parentPort - worker-bridge.ts: Main-thread bridge spawning Worker, relaying postMessage events to EventEmitter matching AgentManagerEvents interface - types.ts: WorkerConfig, SerializableSessionConfig, WorkerMessage protocol Handles dev/production Electron paths, SecurityProfile serialization across worker boundaries, and abort signal propagation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-2-2 - Add worker thread execution to AgentProcessManager Replace Python subprocess spawn with Worker thread creation for AI SDK agents. Add spawnWorkerProcess() using WorkerBridge for postMessage event handling. Update killProcess/killAllProcesses to handle Worker thread termination. Add optional worker field to AgentProcess interface. Keep spawnProcess() and getPythonPath()/ensurePythonEnvReady() for backward compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-2-3 - Add structured progress event handling to AgentEvents Add handleStructuredProgress() and buildProgressData() methods that accept typed progress events from worker threads via postMessage, bypassing text matching. Includes phase regression prevention. Existing parseExecutionPhase() preserved as fallback for backward compatibility during transition. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-2-4 - Write tests for worker thread integration Tests cover: worker spawning, message relay (log/error/progress/stream-event), result handling with exit code mapping, crash handling (worker error/exit events), termination with abort signal, executor lifecycle (start/stop/retry), config management, and AgentManagerEvents compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-3-1 - Create build-orchestrator.ts and subtask-iterator.ts Replaces Python run.py main build loop and agents/coder.py subtask iteration with TypeScript equivalents for the Vercel AI SDK migration. - BuildOrchestrator: drives planning → coding → qa_review → qa_fixing → complete - SubtaskIterator: reads implementation_plan.json, iterates pending subtasks - Phase transitions validated via phase-protocol.ts - Retry tracking, stuck detection, abort signal support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-3-2 - Create spec-orchestrator.ts and qa-loop.ts Add TypeScript replacements for spec_runner.py and qa/loop.py: - spec-orchestrator.ts: Drives spec creation pipeline with dynamic complexity-based phase selection (simple/standard/complex workflows) - qa-loop.ts: QA review/fix iteration loop with recurring issue detection, consecutive error tracking, and human feedback processing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-3-3 - Create parallel-executor.ts and recovery-manager.ts Add concurrent subtask execution with Promise.allSettled() and failure isolation, plus checkpoint/recovery logic for build resume. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-4-1 - Port utility runners (insights, ideation, commit-message) Port insights runner, ideation generator, and commit message generator from Python to TypeScript using Vercel AI SDK v6. Uses createSimpleClient() with streamText/generateText and appropriate tool bindings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-4-2 - Port roadmap, merge-resolver, insight-extractor, and changelog runners Port four utility runners from Python backend to TypeScript using Vercel AI SDK: - roadmap.ts: Multi-phase roadmap generation (discovery + features) with retry logic and feature preservation - merge-resolver.ts: Single-turn merge conflict resolution with factory function - insight-extractor.ts: Session insight extraction with JSON parsing and generic fallback - changelog.ts: Changelog generation supporting tasks, git-history, and branch-diff modes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-4-3 - Replace Python subprocess spawning with TS runners in agent-queue Replace spawnIdeationProcess() and spawnRoadmapProcess() with direct calls to the new TypeScript runners (runIdeation, runRoadmapGeneration). Uses AbortController for cancellation instead of process.kill(). Removes Python environment setup, subprocess spawning, and stdout parsing in favor of structured streaming callbacks from the TS runners. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-5-1 - Port GitHub PR review engine and triage engine Port pr_review_engine.py and triage_engine.py to TypeScript using Vercel AI SDK. Implements multi-pass review workflow (quick scan → parallel security/quality/structural/deep analysis) and issue triage with duplicate detection, spam detection, and feature creep analysis. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-5-2 - Port parallel PR orchestrator, followup reviewer, and GitLab MR review engine Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-6-1 - Add provider settings translation keys to en/settings.json and fr/settings.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-6-2 - Create Provider Settings UI component Add ProviderSettings.tsx with provider selection (Anthropic, OpenAI, Ollama, OpenRouter), per-provider API key input with masked fields, Ollama endpoint URL configuration, test connection button, and per-phase model preferences (spec, planning, coding, QA). All text uses useTranslation('settings') with provider.* namespace keys. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-7-1 - Remove claude-agent-sdk pip dependency Remove claude-agent-sdk from requirements.txt and pyproject.toml. Add a local stub package (apps/backend/claude_agent_sdk/) so existing Python imports resolve to deprecation stubs instead of crashing. Clean up SDK references in worktree.py, auth.py, conftest.py, and EXAMPLES.md. Note: Pre-existing test failure in test_fallback_is_debug_enabled_returns_false is unrelated to these changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-7-2 - Update CLAUDE.md to reflect the new TypeScript agent layer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * auto-claude: subtask-7-3 - Run full verification suite All checks pass: - typecheck: 0 errors - tests: 3548 passed (142 files), 6 skipped - lint: 0 errors (683 pre-existing warnings) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use inputSchema instead of parameters, fix platform/worker patterns (qa-requested) - Changed `parameters` to `inputSchema` in Tool.define() wrapper (AI SDK v6) - Replaced `process.platform === 'win32'` with `isWindows()` from platform utils - Removed `process.exit(1)` from worker thread (terminates naturally) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * TS logic working on kanban tasks * fix: log phase formatting and task completion state transition - Add TaskLogWriter that writes task_logs.json for structured phase sections in the Logs tab (Planning/Coding/Validation) - Emit QA_PASSED/BUILD_COMPLETE task events from worker via postTaskEvent() so XState transitions to human_review instead of stuck - Fix processType in startSpecCreation() from 'task-execution' to 'spec-creation' so exit handler correctly chains into startTaskExecution() - Skip handleProcessExited for successful spec-creation exits to prevent state poisoning before spec→build transition - Add task-event relay in WorkerBridge for worker→main thread task events - Wire orchestrator phase changes to emit kickoff messages per agent type Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add TypeScript worktree manager for task isolation Port Python WorktreeManager.create_worktree() to TypeScript. Tasks now run in isolated git worktrees at .auto-claude/worktrees/tasks/{specId}/ on branch auto-claude/{specId}, matching the Python backend behavior. - Create worktree-manager.ts with idempotent 7-step creation logic - Wire into agent-manager startTaskExecution() and startQAProcess() - Agent cwd set to worktree path so file changes are isolated - Spec files copied to worktree (gitignored, not in checkout) - Falls back to project root if worktree creation fails Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: normalize plan schema fields for subtask tracking LLM planner outputs subtask_id/phase_id instead of id, omits status field, and uses file_paths instead of files_to_modify. The subtask iterator requires status === 'pending' to find work — without it, no subtasks are found and no coding happens. - normalizeSubtaskIds() now adds status: 'pending' default, normalizes phase_id → id, file_paths → files_to_modify, and adds name fallback - ensureSubtaskMarkedCompleted() safety net after each coder session - E2E validated: task 251 shows 2/2 subtasks, no 'Task Incomplete' Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: wire TypeScript runners to IPC handlers, resolve all tsc errors - Replace InsightsExecutor Python subprocess with runInsightsQuery() TS runner (AbortController-based cancellation, streaming events via callback) - Fix pr-handlers.ts type mismatches: phase union cast via Set.has(), findings cast - Fix insights-executor.ts metadata type cast (TaskCategory, TaskComplexity) - Confirm autofix-handlers.ts and mr-review-handlers.ts already have correct imports/TypeScript implementations; tsc now passes with zero errors Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: wire TypeScript Vercel AI SDK changelog runner to IPC handler Replace Python subprocess-based changelogService.generateChangelog() with the TypeScript generateChangelog() runner from ai/runners/changelog.ts, which uses generateText() from the Vercel AI SDK. Emits proper CHANGELOG_GENERATION_PROGRESS and CHANGELOG_GENERATION_COMPLETE events directly from the handler. E2E verified: changelog generation for 24 tasks completes successfully via TypeScript path, producing structured markdown with ### Added, ### Changed, ### Fixed sections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all python logic over to TS * temp_memory_docs * feat: implement Memory System core engine (Steps 1-7) Complete TypeScript memory system with libSQL/Turso storage, covering: - Foundation: types, schema (DDL + FTS5), db client factory - MemoryService: store, search, pattern matching, user-taught memories - EmbeddingService: 5-tier fallback (Ollama 8b/4b/0.6b → OpenAI → ONNX) - Knowledge Graph: tree-sitter AST extraction, chunking, closure tables, incremental indexer with chokidar, impact analysis - Retrieval Pipeline: BM25 + dense vector + graph search, weighted RRF fusion, graph neighborhood boost, cross-encoder reranking (Ollama/Cohere), phase-aware context packing, HyDE fallback - Observer: 17-signal behavioral taxonomy, scratchpad with O(1) analytics, dead-end detection, trust gate (anti-injection), promotion pipeline, parallel scratchpad merger - Active Injection: step injection decider (3 triggers), planner/QA context builders, prefetch plan builder, calibrated stop conditions, prepareStep callback integration in session runner - Agent tools: search_memory, record_memory - IPC: worker-observer proxy, memory IPC handlers 331 tests across 23 test files, 0 TypeScript errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: wire Memory System UI to libSQL backend (Step 8) Update the existing Memory Panel UX to work with the new libSQL-backed MemoryService. Adds singleton factory, rewires IPC handlers, updates shared types with backward-compatible aliases, enhances MemoryCard with confidence bars and trust badges, and adds i18n keys for all 16 memory types. Removes all internal "V5" draft references from production code. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve __dirname ESM error in memory db.ts, clean up V5 naming - Fix ReferenceError: __dirname is not defined in ESM bundles by using dirname(fileURLToPath(import.meta.url)) for sqlite-vec extension path - Rename ParsedV5Memory → ParsedMemoryContent in MemoryCard.tsx - Remove "V5" from comments across constants.ts and MemoriesTab.tsx - Update memory system design doc with reranking and implementation details E2E verified: memory status connected, 6 test memories rendered correctly with category filtering, confidence bars, tags, and related files. 0 TypeScript errors, 3869 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: remove Python backend, rename apps/frontend → apps/desktop - Delete entire Python backend (agents, analysis, CLI, security, QA, runners) except graphiti MCP sidecar and prompts (kept temporarily) - Rename apps/frontend → apps/desktop to reflect Electron desktop app - Update all CI/CD workflows to remove Python jobs and references - Update .husky/pre-commit: remove Python checks, reference apps/desktop - Update .pre-commit-config.yaml: remove Python hooks, reference apps/desktop - Clean 43+ config files referencing apps/frontend → apps/desktop - Remove Python packaging scripts (download-python, verify-linux-packages) - Delete python-env-manager.ts and python-detector.ts from frontend - Add OAuth beta headers for Claude subscription auth - Clean up investigation and migration planning documents Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: delete entire apps/backend, clean all references - Delete apps/backend/ entirely (graphiti, linear integration, Python packaging) - Move prompts from apps/frontend/prompts → apps/desktop/prompts - Remove stale apps/frontend directory - Clean 85+ TypeScript files of apps/backend references (JSDoc, paths, code) - Clean 12+ config files (CI/CD, docs, scripts, .gitignore, dependabot) - Update 3 prompt files with correct TypeScript paths - Delete deprecated scripts (install-backend, test-backend, check_encoding, etc.) - Delete setup-python-backend GitHub Action - Remove Python test files (package-with-python.test.ts, insights-config PYTHONPATH tests) - Fix agent-process.test.ts for deprecated spawnProcess behavior - Update CLAUDE.md, README.md, CONTRIBUTING.md for TypeScript-only architecture Build: 0 tsc errors, 169 test files pass (4031 tests), electron-vite build clean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * memory system * new provider ui * new provider auth and ui * feat: global priority queue with cross-provider fallback and multi-provider header UI Replace per-provider isActive flags with a single global priority queue where all accounts compete in one ordered list. Only one account is "In Use" at any time, and cross-provider fallback happens automatically on 429/401 errors. Key changes: - Data model: remove isActive/priority from ProviderAccount, add billingModel (subscription vs pay-per-use), globalPriorityOrder in AppSettings - Model equivalence system: DEFAULT_MODEL_EQUIVALENCES maps model shorthands across providers with reasoning config (thinking_tokens, reasoning_effort, etc.) - Auth resolver: new resolveAuthFromQueue() walks queue, scores accounts, finds model equivalent, resolves credentials - Session runner: onAccountSwitch callback retries on 429/401 with next account - Client factory: dual-path resolution (queue-based or legacy) - Profile scorer: new scoreProviderAccount() for queue-based availability - AuthStatusIndicator: shows actual active provider name (OpenAI, Google AI, etc.) with provider-specific badge colors instead of hardcoded "Claude Code" - UsageIndicator: Anthropic OAuth shows usage bars, pay-per-use/other providers show "Unlimited" badge; swap reorders global queue - i18n: provider names and billing labels for all 10 providers (en + fr) - IPC: replace PROVIDER_ACCOUNTS_SET_ACTIVE with SET_QUEUE_ORDER, add MODEL_OVERRIDES_SAVE - Settings UI: remove "Set Active" button, derive active from queue position - Tests updated for new provider accounts model (4035 passing) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: enhance provider account management with Codex support - Updated settings handlers to manage provider accounts within a global priority queue, allowing for Codex-specific handling. - Modified UI components to display Codex-related information and subscription options. - Added internationalization support for Codex terminology in English and French. - Improved account addition and deletion logic to reflect changes in global priority order. This update enhances the user experience for managing accounts, particularly for OpenAI's Codex, ensuring a more intuitive interface and better account handling. * provider settings changes * multi-provider ui * feat: concrete per-provider presets and cross-provider tab Replace abstract shorthand-driven presets with concrete per-provider preset definitions so what users see is what actually runs. Move cross-provider configuration from a profile card to its own tab. - Add PROVIDER_PRESET_DEFINITIONS with concrete models for 6 providers (Anthropic, OpenAI, Google, xAI, Mistral, Groq) - Remove "Custom" profile card; 4 presets remain (Auto, Complex, Balanced, Quick) with provider-specific model names on badges - Add Cross-Provider tab in ProviderTabBar (shown when 2+ providers connected) with MixedPhaseEditor and new MixedFeatureEditor - Widen PhaseModelConfig/FeatureModelConfig/ModelType from narrow unions to string to accept any provider's model IDs - Task creation writes phaseProviders to metadata in cross-provider mode - Agent manager prefers specified provider per phase via queue reordering - Provider-aware useResolvedAgentSettings hook with 4-step resolution - i18n keys for cross-provider tab (en + fr) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: pre-PR validation fixes — xhigh thinking level, state management, tests - Add 'xhigh' to VALID_THINKING_LEVELS in phase-config.ts (runtime bug) - Reset customMixedProfileActive when switching away from cross-provider tab - Clean up dead custom profile branch in AgentProfileSelector - Add 14 tests for getProviderPreset/getProviderPresetOrFallback - Add xhigh assertions to phase-config tests - Update stale JSDoc in insights.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: move Claude Code badge from sidebar to terminal toolbar Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Codex API integration — instructions, store, model routing, XState race Three Codex API issues fixed: 1. Pass system prompt via providerOptions.openai.instructions (not system msg) 2. Set store: false (Codex requires it) 3. Use .responses() instead of .chat() for Codex models Worker model routing fix: - runSingleSession now uses baseSession.modelId (queue-resolved) instead of re-resolving via getPhaseModel() which maps opus → claude-opus-4-6 even when the queue selected an OpenAI Codex account XState race condition fix: - Skip fallback timer for successful spec-creation exits (spec → build transition starts a new process immediately, timer would incorrectly force USER_STOPPED on the new process) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: pipeline validation fixes + denylist security model Fix planning log routing, subtask execution, worktree diff tracking, and task completion status. Replace allowlist security model with a denylist that blocks only dangerous system commands while allowing all standard development tools. - Route spec_orchestrator logs to planning phase (not coding) - Merge planning logs from both main and worktree directories - Normalize subtask IDs before coding phase (fixes 0/N completed) - Emit execution-progress events from worker for file watcher re-pointing - Show uncommitted worktree changes in Build for Review (git diff baseBranch) - Fix task showing "Incomplete/Needs Resume" when reviewReason is set - Replace allowlist with 25-command denylist + 15 per-command validators - Fix QA phase transition ordering (markCompleted before transitionPhase) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Codex pipeline halt + UI model display for non-Anthropic providers - Reset all subtask statuses to "pending" after initial planning phase. Some LLMs (particularly OpenAI Codex) create implementation plans with subtasks pre-set to "completed", causing isBuildComplete() to skip coding and QA phases entirely. - Build MODEL_SHORT_LABELS dynamically from ALL_AVAILABLE_MODELS catalog instead of hardcoding only Anthropic shorthands. Now properly displays model names for all providers (OpenAI, Google, Mistral, Groq, xAI). - Set Codex API store parameter to true (matching AI SDK default) for proper subscription API behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * task logs * structured output for all providers with zod validation * codex usage monitoring * fix: pre-PR validation fixes for Vercel AI SDK migration Security: fix worker.ts unsafe cast, sanitize Bearer tokens in error classifier, block --no-preserve-root in rm validator, deny unparseable shell -c commands, redact OAuth tokens in debug logs. Cross-platform: resolve shell dynamically in bash tool (Git Bash/cmd.exe), use findExecutable for ripgrep in grep tool, handle CRLF in read/write/ worktree-manager/auto-merger, use killProcessGracefully for process cleanup. Build: remove stale Python/Graphiti extraResources from package.json, update spec_runner.py marker to session/runner.ts, deduplicate AGENT_CONFIGS in tools/registry.ts, remove hollow test assertion. i18n: add 11 missing FR translation keys in onboarding.json (Ollama config, Voyage embedding model), add memory.info section to en/fr common.json, replace 4 hardcoded strings in MemoriesTab.tsx with t() calls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * provider and auth improvements * harness changes * updates to provider features * pr update * websearch/browser * z-ai and account settings * upgrading model usage with cross provider * usageindication * Optimize usage monitoring: reduce API calls, fix false needs-reauth - Increase polling interval from 30s to 60s for active profile - Increase inactive profile cache TTL from 60s to 5 minutes - Add adaptive cache: drops to 60s when active usage >80% session or >90% weekly - Add request coalescing for getAllProfilesUsage() to prevent duplicate fetches - Stagger same-provider fetches with 15s delay (prevents burst-hitting same API) - Add 10-minute backoff for 429 rate limits (vs 2min general failure cooldown) - Stop force-refreshing on AccountSettings open (use cached data + push updates) - Fix false "needs re-auth" flag: clear needsReauthProfiles when valid token obtained - Remove noisy ProjectStore subtask completion diagnostic logging Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * usage+worktree+harness * oauth+structuredoutput * husky fixes * onboarding and memorycleanup * memorycleanup * new spec system * fixes * fix: resolve CodeQL high and medium security alerts Address 60+ CodeQL security findings blocking PR merge: - Insecure temp files: use mkdtempSync + atomic write-rename (26 alerts) - TOCTOU race conditions: replace existsSync→act with try/catch (8 alerts) - Shell injection: replace execSync with execFileSync + args array (1 alert) - Network data validation: add type checks before disk writes (10 alerts) - File data in requests: validate tokens/credentials before use (6 alerts) - Log injection: sanitize control characters before logging (3 alerts) - Incomplete string escaping: eliminate shell interpolation (1 alert) - Dead code: remove useless conditionals and assignments (5 alerts) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve remaining 7 CodeQL high-severity TOCTOU race conditions - read.ts: use fstat via fd for PDF size, avoid stat→readFile gap - spec-number-lock.ts: remove existsSync pre-checks, rely on atomic wx flag and direct readFileSync with ENOENT handling - settings-utils.ts: remove access() pre-check, readFile directly with catch - log-service.ts: derive sizeBytes from Buffer.byteLength of read content instead of separate statSync - roadmap.ts: serialize from in-memory data to avoid re-read gap - subtask-iterator-restamp.test.ts: use fd.stat() + fd.readFile() on same fd Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: trigger CodeQL re-evaluation Force GitHub code scanning PR check to re-evaluate after security fixes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: eliminate TOCTOU by using fd-based file operations throughout - read.ts: open fd once, use fstatSync + readFileSync(fd) for all paths (directory check, image, PDF, text) through a single file descriptor - roadmap.ts: read via openSync/readFileSync(fd) instead of path-based read to decouple the "check" from the subsequent writeFileSync - subtask-iterator-restamp.test.ts: use fd.stat() instead of path-based stat for mtime recording Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve remaining TOCTOU alerts in roadmap, test, and bump-version - roadmap.ts: atomic write via temp file + rename to break path flow - subtask-iterator-restamp.test.ts: compare content snapshots instead of stat+read (eliminates multi-operation path reuse) - bump-version.js: replace existsSync pre-checks with try/catch on read Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
950 lines
33 KiB
JSON
950 lines
33 KiB
JSON
{
|
||
"$schema": "Design System Guidelines v2.0",
|
||
"meta": {
|
||
"name": "Auto-Build UI Design System",
|
||
"description": "A modern, professional design system inspired by Fey/Oscura aesthetics. Features deep dark mode with warm yellow accents, muted semantic colors, and clean typography.",
|
||
"designPhilosophy": "Minimal, data-focused interfaces optimized for dark mode. Near-black backgrounds with warm yellow accents create visual hierarchy. Color is reserved primarily for semantic meaning (success/error) while neutral grays handle most UI elements.",
|
||
"defaultTheme": "Oscura Midnight - deep dark with saturated yellow accent"
|
||
},
|
||
|
||
"designPrinciples": {
|
||
"core": [
|
||
{
|
||
"name": "Dark-First Design",
|
||
"description": "Design primarily for dark mode with near-black backgrounds (#0B0B0F). Light mode is a secondary consideration with warm off-white tones."
|
||
},
|
||
{
|
||
"name": "Semantic Color Usage",
|
||
"description": "Reserve color primarily for meaning - green for positive/success, red for negative/error. Most UI elements should be neutral grays with the accent color for interactive highlights."
|
||
},
|
||
{
|
||
"name": "Generous Whitespace",
|
||
"description": "Allow content to breathe with ample padding and margins. Never crowd elements together."
|
||
},
|
||
{
|
||
"name": "Card-Based Modularity",
|
||
"description": "Organize content into distinct card modules. In dark mode, cards use subtle borders rather than shadows for definition."
|
||
},
|
||
{
|
||
"name": "Visual Hierarchy Through Weight",
|
||
"description": "Use font weight, size, and subtle color differences to establish hierarchy rather than aggressive styling"
|
||
},
|
||
{
|
||
"name": "Data-Focused Clarity",
|
||
"description": "Optimize for readability of data, numbers, and financial information. Use monospace fonts for numerical data."
|
||
}
|
||
],
|
||
"donts": [
|
||
"Avoid pure black (#000000) - use near-black (#0B0B0F) instead",
|
||
"Don't overuse the accent color - reserve it for key interactive elements",
|
||
"Avoid cramped layouts - maintain minimum 16px spacing between elements",
|
||
"Don't use sharp corners - minimum 8px border-radius on interactive elements",
|
||
"In dark mode, avoid heavy shadows - use subtle borders instead"
|
||
]
|
||
},
|
||
|
||
"themeSystem": {
|
||
"description": "Multi-theme system with 7 color themes, each supporting light and dark modes",
|
||
"implementation": "Use data-theme attribute for color theme and .dark class for mode. Default theme requires no data-theme attribute.",
|
||
"cssSelectors": {
|
||
"lightDefault": ":root",
|
||
"darkDefault": ".dark",
|
||
"themeVariant": "[data-theme=\"{id}\"]",
|
||
"darkThemeVariant": "[data-theme=\"{id}\"].dark"
|
||
},
|
||
"examples": [
|
||
"<html> (default light)",
|
||
"<html class=\"dark\"> (default dark - Oscura Midnight)",
|
||
"<html data-theme=\"dusk\" class=\"dark\"> (dusk dark - slightly lighter)",
|
||
"<html data-theme=\"lime\"> (lime light)"
|
||
],
|
||
"colorThemes": [
|
||
{
|
||
"id": "default",
|
||
"name": "Default",
|
||
"description": "Oscura Midnight - deepest dark with saturated yellow accent, inspired by Fey/Oscura",
|
||
"previewColors": {
|
||
"lightBg": "#F2F2ED",
|
||
"lightAccent": "#A5A66A",
|
||
"darkBg": "#0B0B0F",
|
||
"darkAccent": "#D6D876"
|
||
},
|
||
"semanticColors": {
|
||
"success": "#4EBE96",
|
||
"error": { "light": "#D84F68", "dark": "#FF5C5C" },
|
||
"warning": "#D2D714",
|
||
"info": "#479FFA"
|
||
},
|
||
"note": "No data-theme attribute needed - this is the base theme. Best for financial/data-heavy applications."
|
||
},
|
||
{
|
||
"id": "dusk",
|
||
"name": "Dusk",
|
||
"description": "Warmer Oscura variant with slightly lighter dark mode",
|
||
"previewColors": {
|
||
"lightBg": "#F5F5F0",
|
||
"lightAccent": "#B8B978",
|
||
"darkBg": "#131419",
|
||
"darkAccent": "#E6E7A3"
|
||
},
|
||
"semanticColors": {
|
||
"success": "#4EBE96",
|
||
"error": "#D84F68",
|
||
"warning": "#D2D714",
|
||
"info": "#479FFA"
|
||
},
|
||
"note": "Same accent family as Default but with warmer backgrounds and softer colors"
|
||
},
|
||
{
|
||
"id": "lime",
|
||
"name": "Lime",
|
||
"description": "Fresh, energetic lime/chartreuse with purple accents",
|
||
"previewColors": {
|
||
"lightBg": "#E8F5A3",
|
||
"darkBg": "#0F0F1A",
|
||
"accent": "#7C3AED"
|
||
}
|
||
},
|
||
{
|
||
"id": "ocean",
|
||
"name": "Ocean",
|
||
"description": "Calm, professional blue tones",
|
||
"previewColors": {
|
||
"lightBg": "#E0F2FE",
|
||
"darkBg": "#082F49",
|
||
"accent": "#0284C7"
|
||
}
|
||
},
|
||
{
|
||
"id": "retro",
|
||
"name": "Retro",
|
||
"description": "Warm, nostalgic amber/orange vibes",
|
||
"previewColors": {
|
||
"lightBg": "#FEF3C7",
|
||
"darkBg": "#1C1917",
|
||
"accent": "#D97706"
|
||
}
|
||
},
|
||
{
|
||
"id": "neo",
|
||
"name": "Neo",
|
||
"description": "Modern cyberpunk pink/magenta",
|
||
"previewColors": {
|
||
"lightBg": "#FDF4FF",
|
||
"darkBg": "#0F0720",
|
||
"accent": "#D946EF"
|
||
}
|
||
},
|
||
{
|
||
"id": "forest",
|
||
"name": "Forest",
|
||
"description": "Natural, earthy green tones",
|
||
"previewColors": {
|
||
"lightBg": "#DCFCE7",
|
||
"darkBg": "#052E16",
|
||
"accent": "#16A34A"
|
||
}
|
||
}
|
||
],
|
||
"modes": ["light", "dark"]
|
||
},
|
||
|
||
"colors": {
|
||
"note": "These are the Default theme colors (Oscura Midnight). See themeSystem for all available themes.",
|
||
"cssVariablePrefix": "--color-",
|
||
|
||
"lightMode": {
|
||
"background": {
|
||
"primary": "#F2F2ED",
|
||
"primaryDescription": "Warm off-white with subtle cream tint",
|
||
"primaryVariable": "--color-background-primary",
|
||
"secondary": "#E8E8E3",
|
||
"secondaryDescription": "Slightly darker warm gray for cards",
|
||
"neutral": "#EDEDE8"
|
||
},
|
||
"surface": {
|
||
"card": "#FFFFFF",
|
||
"elevated": "#FFFFFF",
|
||
"overlay": "rgba(0, 0, 0, 0.5)"
|
||
},
|
||
"text": {
|
||
"primary": "#0B0B0F",
|
||
"primaryDescription": "Near-black for maximum readability",
|
||
"secondary": "#5C6974",
|
||
"secondaryDescription": "Muted gray for supporting text",
|
||
"tertiary": "#868F97",
|
||
"inverse": "#0B0B0F"
|
||
},
|
||
"accent": {
|
||
"primary": "#A5A66A",
|
||
"primaryDescription": "Muted olive/yellow for light mode",
|
||
"primaryHover": "#8E8F5A",
|
||
"primaryLight": "#EFEFE0"
|
||
},
|
||
"border": {
|
||
"default": "#DEDED9",
|
||
"focus": "#A5A66A"
|
||
}
|
||
},
|
||
|
||
"darkMode": {
|
||
"background": {
|
||
"primary": "#0B0B0F",
|
||
"primaryDescription": "Near-black - deepest dark background (OLED optimized)",
|
||
"primaryVariable": "--color-background-primary",
|
||
"secondary": "#121216",
|
||
"secondaryDescription": "Slightly lighter for cards and surfaces",
|
||
"neutral": "#0E0E12"
|
||
},
|
||
"surface": {
|
||
"card": "#121216",
|
||
"cardDescription": "Same as background.secondary for subtle elevation",
|
||
"elevated": "#1A1A1F",
|
||
"overlay": "rgba(0, 0, 0, 0.85)"
|
||
},
|
||
"text": {
|
||
"primary": "#E6E6E6",
|
||
"primaryDescription": "Light gray - main text color",
|
||
"secondary": "#868F97",
|
||
"secondaryDescription": "Muted gray for supporting text",
|
||
"tertiary": "#5C6974",
|
||
"inverse": "#0B0B0F"
|
||
},
|
||
"accent": {
|
||
"primary": "#D6D876",
|
||
"primaryDescription": "Saturated yellow - Oscura accent (more vibrant for better contrast)",
|
||
"primaryHover": "#C5C85A",
|
||
"primaryLight": "#2A2A1F",
|
||
"primaryLightDescription": "Dark yellowish background for selected states"
|
||
},
|
||
"border": {
|
||
"default": "#232323",
|
||
"defaultDescription": "Subtle dark border for card definition",
|
||
"focus": "#D6D876"
|
||
}
|
||
},
|
||
|
||
"semantic": {
|
||
"success": "#4EBE96",
|
||
"successLight": { "light": "#E0F5ED", "dark": "#1A2924" },
|
||
"successDescription": "Teal green - for success states, positive values, confirmations",
|
||
"warning": "#D2D714",
|
||
"warningLight": { "light": "#F5F5D0", "dark": "#262618" },
|
||
"warningDescription": "Yellow-green - for warnings, caution states",
|
||
"error": { "light": "#D84F68", "dark": "#FF5C5C" },
|
||
"errorLight": { "light": "#FCE8EC", "dark": "#2A1A1A" },
|
||
"errorDescription": "Red - for errors, negative values, destructive actions",
|
||
"info": "#479FFA",
|
||
"infoLight": { "light": "#E8F4FF", "dark": "#1A2230" },
|
||
"infoDescription": "Blue - for links and informational elements"
|
||
},
|
||
|
||
"shadows": {
|
||
"lightMode": {
|
||
"sm": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||
"md": "0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.05)",
|
||
"lg": "0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.05)",
|
||
"xl": "0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.04)",
|
||
"focus": "0 0 0 3px rgba(165, 166, 106, 0.2)"
|
||
},
|
||
"darkMode": {
|
||
"note": "Shadows are deeper in dark mode. Cards primarily use borders for definition.",
|
||
"sm": "0 1px 2px 0 rgba(0, 0, 0, 0.6)",
|
||
"md": "0 4px 6px -1px rgba(0, 0, 0, 0.7)",
|
||
"lg": "0 10px 15px -3px rgba(0, 0, 0, 0.8)",
|
||
"xl": "0 20px 25px -5px rgba(0, 0, 0, 0.9)",
|
||
"focus": "0 0 0 2px rgba(230, 231, 163, 0.2)"
|
||
}
|
||
}
|
||
},
|
||
|
||
"typography": {
|
||
"fontFamily": {
|
||
"primary": "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
||
"primaryDescription": "Inter is the preferred font. Fall back to system fonts for performance.",
|
||
"mono": "'JetBrains Mono', 'Fira Code', 'SF Mono', monospace",
|
||
"monoDescription": "For code, technical content, and fixed-width displays"
|
||
},
|
||
"scale": {
|
||
"displayLarge": {
|
||
"size": "36px",
|
||
"lineHeight": "44px",
|
||
"weight": "700",
|
||
"letterSpacing": "-0.02em",
|
||
"usage": "Page titles, hero text"
|
||
},
|
||
"displayMedium": {
|
||
"size": "30px",
|
||
"lineHeight": "38px",
|
||
"weight": "700",
|
||
"letterSpacing": "-0.02em",
|
||
"usage": "Section headers, card titles for large cards"
|
||
},
|
||
"headingLarge": {
|
||
"size": "24px",
|
||
"lineHeight": "32px",
|
||
"weight": "600",
|
||
"letterSpacing": "-0.01em",
|
||
"usage": "Card headings, modal titles"
|
||
},
|
||
"headingMedium": {
|
||
"size": "20px",
|
||
"lineHeight": "28px",
|
||
"weight": "600",
|
||
"letterSpacing": "-0.01em",
|
||
"usage": "Subsection headings"
|
||
},
|
||
"headingSmall": {
|
||
"size": "16px",
|
||
"lineHeight": "24px",
|
||
"weight": "600",
|
||
"usage": "List item titles, small card headings"
|
||
},
|
||
"bodyLarge": {
|
||
"size": "16px",
|
||
"lineHeight": "24px",
|
||
"weight": "400",
|
||
"usage": "Primary body text, descriptions"
|
||
},
|
||
"bodyMedium": {
|
||
"size": "14px",
|
||
"lineHeight": "20px",
|
||
"weight": "400",
|
||
"usage": "Secondary body text, form labels"
|
||
},
|
||
"bodySmall": {
|
||
"size": "12px",
|
||
"lineHeight": "16px",
|
||
"weight": "400",
|
||
"usage": "Captions, timestamps, helper text"
|
||
},
|
||
"label": {
|
||
"size": "14px",
|
||
"lineHeight": "20px",
|
||
"weight": "500",
|
||
"usage": "Form labels, button text"
|
||
},
|
||
"labelSmall": {
|
||
"size": "12px",
|
||
"lineHeight": "16px",
|
||
"weight": "500",
|
||
"letterSpacing": "0.02em",
|
||
"usage": "Badges, tags, small labels"
|
||
}
|
||
}
|
||
},
|
||
|
||
"spacing": {
|
||
"base": "4px",
|
||
"scale": {
|
||
"0": "0px",
|
||
"1": "4px",
|
||
"2": "8px",
|
||
"3": "12px",
|
||
"4": "16px",
|
||
"5": "20px",
|
||
"6": "24px",
|
||
"8": "32px",
|
||
"10": "40px",
|
||
"12": "48px",
|
||
"16": "64px",
|
||
"20": "80px"
|
||
},
|
||
"guidelines": {
|
||
"cardPadding": "24px",
|
||
"cardPaddingDescription": "Internal padding for card content",
|
||
"cardGap": "16px",
|
||
"cardGapDescription": "Gap between cards in a grid",
|
||
"sectionGap": "32px",
|
||
"sectionGapDescription": "Vertical space between major sections",
|
||
"elementGap": "12px",
|
||
"elementGapDescription": "Space between related elements within a card",
|
||
"tightGap": "8px",
|
||
"tightGapDescription": "Compact spacing for dense lists or small elements"
|
||
}
|
||
},
|
||
|
||
"borderRadius": {
|
||
"none": "0px",
|
||
"sm": "4px",
|
||
"smUsage": "Small badges, inline elements",
|
||
"md": "8px",
|
||
"mdUsage": "Buttons, inputs, small interactive elements",
|
||
"lg": "12px",
|
||
"lgUsage": "Dropdowns, popovers, smaller cards",
|
||
"xl": "16px",
|
||
"xlUsage": "Standard cards, modals",
|
||
"2xl": "20px",
|
||
"2xlUsage": "Large cards, primary containers",
|
||
"3xl": "24px",
|
||
"3xlUsage": "Hero cards, featured content",
|
||
"full": "9999px",
|
||
"fullUsage": "Avatars, pills, circular buttons, tags"
|
||
},
|
||
|
||
"shadows": {
|
||
"note": "Use CSS variable --shadow-{size}. Values differ between light and dark mode.",
|
||
"lightMode": {
|
||
"none": "none",
|
||
"sm": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
||
"smUsage": "Subtle elevation for buttons",
|
||
"md": "0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.05)",
|
||
"mdUsage": "Cards resting on colored backgrounds",
|
||
"lg": "0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.05)",
|
||
"lgUsage": "Elevated cards, dropdowns, popovers",
|
||
"xl": "0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.04)",
|
||
"xlUsage": "Modals, dialogs",
|
||
"focus": "0 0 0 3px rgba(165, 166, 106, 0.2)",
|
||
"focusUsage": "Focus ring for interactive elements (uses accent color)"
|
||
},
|
||
"darkMode": {
|
||
"note": "Deeper shadows in dark mode, but prefer borders for card definition",
|
||
"sm": "0 1px 2px 0 rgba(0, 0, 0, 0.6)",
|
||
"md": "0 4px 6px -1px rgba(0, 0, 0, 0.7)",
|
||
"lg": "0 10px 15px -3px rgba(0, 0, 0, 0.8)",
|
||
"xl": "0 20px 25px -5px rgba(0, 0, 0, 0.9)",
|
||
"focus": "0 0 0 2px rgba(230, 231, 163, 0.2)"
|
||
}
|
||
},
|
||
|
||
"components": {
|
||
"card": {
|
||
"description": "Primary container for content modules. Background varies by mode.",
|
||
"styling": {
|
||
"background": "var(--color-surface-card)",
|
||
"lightModeValue": "#FFFFFF",
|
||
"darkModeValue": "#121216",
|
||
"borderRadius": "xl (16px) to 2xl (20px)",
|
||
"padding": "24px",
|
||
"shadow": "var(--shadow-md) - soft and diffused",
|
||
"border": "1px solid var(--color-border-default)"
|
||
},
|
||
"modeSpecific": {
|
||
"lightMode": {
|
||
"background": "#FFFFFF",
|
||
"useShadow": true,
|
||
"useBorder": "optional, very subtle"
|
||
},
|
||
"darkMode": {
|
||
"background": "#121216",
|
||
"useShadow": false,
|
||
"useBorder": "required - 1px solid #232323 for definition"
|
||
}
|
||
},
|
||
"variants": {
|
||
"default": "Standard card with mode-appropriate styling",
|
||
"interactive": "Adds hover state with slight scale or shadow/border change",
|
||
"outlined": "No shadow, always uses border"
|
||
}
|
||
},
|
||
|
||
"button": {
|
||
"description": "Interactive buttons with clear hierarchy. Generous padding and fully rounded or moderately rounded corners.",
|
||
"sizing": {
|
||
"sm": { "height": "32px", "padding": "8px 12px", "fontSize": "12px" },
|
||
"md": { "height": "40px", "padding": "10px 16px", "fontSize": "14px" },
|
||
"lg": { "height": "48px", "padding": "12px 24px", "fontSize": "16px" }
|
||
},
|
||
"variants": {
|
||
"primary": {
|
||
"background": "var(--color-accent-primary)",
|
||
"lightModeValue": "#A5A66A",
|
||
"darkModeValue": "#D6D876",
|
||
"text": "var(--color-text-inverse)",
|
||
"textNote": "Dark text on yellow accent for maximum contrast",
|
||
"borderRadius": "md (8px) or full for pill style",
|
||
"hover": "var(--color-accent-primary-hover)"
|
||
},
|
||
"secondary": {
|
||
"background": "transparent",
|
||
"text": "var(--color-text-primary)",
|
||
"border": "1px solid var(--color-border-default)",
|
||
"borderRadius": "md (8px) or full",
|
||
"hover": "Subtle background tint"
|
||
},
|
||
"ghost": {
|
||
"background": "transparent",
|
||
"text": "var(--color-text-secondary)",
|
||
"hover": "Subtle background"
|
||
},
|
||
"success": {
|
||
"background": "var(--color-semantic-success)",
|
||
"value": "#4EBE96",
|
||
"text": "white"
|
||
},
|
||
"danger": {
|
||
"background": "var(--color-semantic-error)",
|
||
"lightValue": "#D84F68",
|
||
"darkValue": "#FF5C5C",
|
||
"text": "white"
|
||
}
|
||
}
|
||
},
|
||
|
||
"avatar": {
|
||
"description": "Circular user/entity images with optional border and status indicators.",
|
||
"sizing": {
|
||
"xs": "24px",
|
||
"sm": "32px",
|
||
"md": "40px",
|
||
"lg": "56px",
|
||
"xl": "80px",
|
||
"2xl": "120px"
|
||
},
|
||
"styling": {
|
||
"borderRadius": "full (50%)",
|
||
"border": "2px solid white (creates separation when stacked)",
|
||
"fallback": "Initials on gradient or solid color background"
|
||
},
|
||
"stackedGroup": {
|
||
"overlap": "-8px margin for grouped avatars",
|
||
"maxVisible": "4-5 with '+N' overflow indicator"
|
||
}
|
||
},
|
||
|
||
"badge": {
|
||
"description": "Small labels for status, categories, or counts. Pill-shaped with subtle backgrounds.",
|
||
"styling": {
|
||
"borderRadius": "full (pill shape)",
|
||
"padding": "4px 12px",
|
||
"fontSize": "labelSmall (12px)",
|
||
"fontWeight": "500"
|
||
},
|
||
"variants": {
|
||
"default": {
|
||
"background": "var(--color-background-secondary)",
|
||
"text": "var(--color-text-secondary)"
|
||
},
|
||
"primary": {
|
||
"background": "var(--color-accent-primary-light)",
|
||
"text": "var(--color-accent-primary)"
|
||
},
|
||
"success": {
|
||
"background": "var(--color-semantic-success-light)",
|
||
"text": "var(--color-semantic-success)"
|
||
},
|
||
"warning": {
|
||
"background": "var(--color-semantic-warning-light)",
|
||
"text": "var(--color-semantic-warning)"
|
||
},
|
||
"error": {
|
||
"background": "var(--color-semantic-error-light)",
|
||
"text": "var(--color-semantic-error)"
|
||
},
|
||
"outline": {
|
||
"background": "transparent",
|
||
"border": "1px solid var(--color-border-default)",
|
||
"text": "var(--color-text-secondary)"
|
||
}
|
||
}
|
||
},
|
||
|
||
"input": {
|
||
"description": "Text inputs with clear boundaries and focus states.",
|
||
"styling": {
|
||
"height": "40px (md) or 48px (lg)",
|
||
"padding": "12px 16px",
|
||
"borderRadius": "md (8px)",
|
||
"border": "1px solid var(--color-border-default)",
|
||
"background": "var(--color-surface-card)",
|
||
"fontSize": "bodyMedium (14px)",
|
||
"color": "var(--color-text-primary)"
|
||
},
|
||
"states": {
|
||
"default": { "border": "var(--color-border-default)" },
|
||
"hover": { "border": "slightly lighter/darker depending on mode" },
|
||
"focus": { "border": "var(--color-accent-primary)", "shadow": "var(--shadow-focus)" },
|
||
"error": { "border": "var(--color-semantic-error)" },
|
||
"disabled": { "background": "var(--color-background-secondary)", "opacity": "0.6" }
|
||
}
|
||
},
|
||
|
||
"progressCircle": {
|
||
"description": "Circular progress indicators showing completion percentage. Central number with surrounding arc.",
|
||
"sizing": {
|
||
"sm": "40px diameter",
|
||
"md": "56px diameter",
|
||
"lg": "80px diameter"
|
||
},
|
||
"styling": {
|
||
"trackColor": "var(--color-border-default)",
|
||
"lightTrack": "#DEDED9",
|
||
"darkTrack": "#232323",
|
||
"fillColor": "var(--color-accent-primary) or semantic colors",
|
||
"strokeWidth": "4-6px",
|
||
"centerText": "Percentage in bold"
|
||
}
|
||
},
|
||
|
||
"progressBar": {
|
||
"description": "Linear progress indicator for horizontal space.",
|
||
"styling": {
|
||
"height": "6px or 8px",
|
||
"borderRadius": "full",
|
||
"trackColor": "var(--color-border-default)",
|
||
"fillColor": "var(--color-accent-primary) or semantic colors"
|
||
}
|
||
},
|
||
|
||
"notification": {
|
||
"description": "List items for notifications or activity feeds.",
|
||
"styling": {
|
||
"padding": "16px",
|
||
"borderBottom": "1px solid border.default (except last item)",
|
||
"avatar": "sm (32px) on left",
|
||
"layout": "Avatar | Content (title, description, timestamp) | Actions"
|
||
},
|
||
"elements": {
|
||
"title": "headingSmall weight, text.primary",
|
||
"description": "bodySmall, text.secondary",
|
||
"timestamp": "bodySmall, text.tertiary",
|
||
"actions": "Small buttons or icon buttons"
|
||
}
|
||
},
|
||
|
||
"listItem": {
|
||
"description": "Generic list item for team members, menu items, etc.",
|
||
"styling": {
|
||
"padding": "12px 16px",
|
||
"borderRadius": "lg (12px) for standalone, none for continuous lists",
|
||
"hover": "Subtle background change"
|
||
},
|
||
"layout": "Leading element (avatar/icon) | Content | Trailing element (badge/action)"
|
||
},
|
||
|
||
"calendar": {
|
||
"description": "Date picker grid with clear day cells and selection states.",
|
||
"styling": {
|
||
"dayCell": { "size": "36px", "borderRadius": "md (8px)" },
|
||
"selectedDay": {
|
||
"background": "var(--color-accent-primary)",
|
||
"text": "var(--color-text-inverse)",
|
||
"borderRadius": "full"
|
||
},
|
||
"todayIndicator": "var(--color-accent-primary) text color or dot",
|
||
"rangeSelection": "var(--color-accent-primary-light) background for range days"
|
||
}
|
||
},
|
||
|
||
"toggle": {
|
||
"description": "On/off switch for settings.",
|
||
"sizing": {
|
||
"width": "44px",
|
||
"height": "24px",
|
||
"thumbSize": "20px"
|
||
},
|
||
"styling": {
|
||
"off": {
|
||
"track": "var(--color-border-default)",
|
||
"lightTrack": "#DEDED9",
|
||
"darkTrack": "#232323",
|
||
"thumb": "white"
|
||
},
|
||
"on": {
|
||
"track": "var(--color-accent-primary)",
|
||
"lightTrack": "#A5A66A",
|
||
"darkTrack": "#D6D876",
|
||
"thumb": "var(--color-text-inverse)",
|
||
"thumbNote": "Dark thumb on yellow track for contrast"
|
||
},
|
||
"transition": "smooth 200ms"
|
||
}
|
||
},
|
||
|
||
"dropdown": {
|
||
"description": "Select menus and dropdown panels.",
|
||
"styling": {
|
||
"background": "surface.card",
|
||
"borderRadius": "lg (12px)",
|
||
"shadow": "lg",
|
||
"padding": "8px",
|
||
"itemPadding": "10px 12px",
|
||
"itemBorderRadius": "md (8px)",
|
||
"itemHover": "Light gray background"
|
||
}
|
||
},
|
||
|
||
"modal": {
|
||
"description": "Dialog overlays for focused tasks.",
|
||
"styling": {
|
||
"background": "surface.card",
|
||
"borderRadius": "2xl (20px)",
|
||
"shadow": "xl",
|
||
"padding": "24px",
|
||
"maxWidth": "480px (sm), 640px (md), 800px (lg)",
|
||
"overlay": "surface.overlay with blur optional"
|
||
}
|
||
},
|
||
|
||
"tabs": {
|
||
"description": "Tab navigation for switching between views.",
|
||
"styling": {
|
||
"tabPadding": "12px 16px",
|
||
"activeIndicator": "Bottom border (2px var(--color-accent-primary)) or pill background",
|
||
"inactiveText": "var(--color-text-secondary)",
|
||
"activeText": "var(--color-text-primary) or var(--color-accent-primary)"
|
||
}
|
||
},
|
||
|
||
"iconButton": {
|
||
"description": "Square or circular buttons containing only an icon.",
|
||
"sizing": {
|
||
"sm": "32px",
|
||
"md": "40px",
|
||
"lg": "48px"
|
||
},
|
||
"styling": {
|
||
"borderRadius": "md (8px) or full",
|
||
"iconSize": "16px (sm), 20px (md), 24px (lg)"
|
||
}
|
||
},
|
||
|
||
"menuDots": {
|
||
"description": "Three-dot overflow menu trigger (vertical or horizontal).",
|
||
"styling": {
|
||
"iconButton": "ghost variant",
|
||
"size": "md (40px)",
|
||
"hoverBackground": "Subtle gray"
|
||
}
|
||
}
|
||
},
|
||
|
||
"layout": {
|
||
"principles": [
|
||
"Use a flexible grid system - CSS Grid or Flexbox",
|
||
"Cards should align on a consistent grid",
|
||
"Bento-box style layouts where cards of different sizes create visual interest",
|
||
"Maintain consistent gutters (16px minimum) between all cards"
|
||
],
|
||
"containerMaxWidth": "1440px",
|
||
"containerPadding": "24px on desktop, 16px on mobile",
|
||
"gridColumns": "12-column grid for complex layouts",
|
||
"gridGap": "16px to 24px",
|
||
"sidebar": {
|
||
"width": "240px to 280px",
|
||
"collapsedWidth": "64px",
|
||
"background": "surface.card or slightly tinted"
|
||
}
|
||
},
|
||
|
||
"animation": {
|
||
"principles": [
|
||
"Subtle and purposeful - don't animate for animation's sake",
|
||
"Use animation to provide feedback and improve perceived performance",
|
||
"Prefer transforms and opacity for smooth 60fps animations"
|
||
],
|
||
"durations": {
|
||
"instant": "50ms",
|
||
"fast": "150ms",
|
||
"normal": "250ms",
|
||
"slow": "400ms"
|
||
},
|
||
"easings": {
|
||
"default": "cubic-bezier(0.4, 0, 0.2, 1)",
|
||
"enter": "cubic-bezier(0, 0, 0.2, 1)",
|
||
"exit": "cubic-bezier(0.4, 0, 1, 1)",
|
||
"bounce": "cubic-bezier(0.68, -0.55, 0.265, 1.55)"
|
||
},
|
||
"commonAnimations": {
|
||
"fadeIn": "opacity 0 to 1, duration normal",
|
||
"slideUp": "translateY(8px) to 0, opacity 0 to 1",
|
||
"scale": "scale(0.95) to scale(1) for modals/dropdowns",
|
||
"hover": "slight scale(1.02) or shadow increase"
|
||
}
|
||
},
|
||
|
||
"icons": {
|
||
"style": "Outlined or light stroke weight, consistent sizing",
|
||
"recommendedSets": ["Lucide", "Heroicons", "Phosphor"],
|
||
"sizing": {
|
||
"xs": "12px",
|
||
"sm": "16px",
|
||
"md": "20px",
|
||
"lg": "24px",
|
||
"xl": "32px"
|
||
},
|
||
"strokeWidth": "1.5px to 2px for outlined icons",
|
||
"color": "Inherit from text color or use semantic colors"
|
||
},
|
||
|
||
"accessibility": {
|
||
"focusVisible": {
|
||
"outline": "2px solid var(--color-accent-primary)",
|
||
"outlineOffset": "2px",
|
||
"or": "var(--shadow-focus) ring"
|
||
},
|
||
"minimumTouchTarget": "44px × 44px",
|
||
"colorContrast": "Minimum 4.5:1 for normal text, 3:1 for large text",
|
||
"reduceMotion": "Respect prefers-reduced-motion media query",
|
||
"darkModeNote": "Yellow accent (#D6D876) on near-black (#0B0B0F) provides ~11:1 contrast ratio"
|
||
},
|
||
|
||
"darkModeDetails": {
|
||
"note": "Oscura Midnight - inspired by Fey/Oscura VS Code theme. Saturated yellow accent with muted semantic colors.",
|
||
"implementation": "Add 'dark' class to document root (<html class=\"dark\">) to enable dark mode. All CSS variables automatically update.",
|
||
"designPrinciples": [
|
||
"Near-black backgrounds (#0B0B0F) for maximum contrast and OLED optimization",
|
||
"Light gray text hierarchy (#E6E6E6 → #868F97 → #5C6974)",
|
||
"Saturated yellow accent (#D6D876) for interactive elements - vibrant enough for good contrast",
|
||
"Muted semantic colors - teal success (#4EBE96), soft red errors (#FF5C5C)",
|
||
"Subtle borders (#232323) instead of shadows for card definition",
|
||
"Use color sparingly - mostly grayscale with semantic colors for meaning"
|
||
],
|
||
"colors": {
|
||
"background": {
|
||
"primary": "#0B0B0F",
|
||
"primaryVariable": "--color-background-primary",
|
||
"primaryDescription": "Near-black - main app background (OLED optimized)",
|
||
"secondary": "#121216",
|
||
"secondaryVariable": "--color-background-secondary",
|
||
"secondaryDescription": "Slightly lighter for cards and elevated surfaces",
|
||
"neutral": "#0E0E12",
|
||
"neutralVariable": "--color-background-neutral"
|
||
},
|
||
"surface": {
|
||
"card": "#121216",
|
||
"cardVariable": "--color-surface-card",
|
||
"cardDescription": "Dark card surface - same as background.secondary",
|
||
"elevated": "#1A1A1F",
|
||
"elevatedVariable": "--color-surface-elevated",
|
||
"overlay": "rgba(0, 0, 0, 0.85)"
|
||
},
|
||
"text": {
|
||
"primary": "#E6E6E6",
|
||
"primaryVariable": "--color-text-primary",
|
||
"primaryDescription": "Light gray for maximum readability",
|
||
"secondary": "#868F97",
|
||
"secondaryDescription": "Muted gray for secondary content",
|
||
"tertiary": "#5C6974",
|
||
"tertiaryDescription": "Darkest text - captions, disabled",
|
||
"inverse": "#0B0B0F",
|
||
"inverseDescription": "Dark text on light backgrounds (e.g., accent buttons)"
|
||
},
|
||
"accent": {
|
||
"primary": "#D6D876",
|
||
"primaryVariable": "--color-accent-primary",
|
||
"primaryDescription": "Saturated yellow - more vibrant than pale yellow for better contrast",
|
||
"primaryHover": "#C5C85A",
|
||
"primaryHoverVariable": "--color-accent-primary-hover",
|
||
"primaryLight": "#2A2A1F",
|
||
"primaryLightVariable": "--color-accent-primary-light",
|
||
"primaryLightDescription": "Dark yellowish background for selected states"
|
||
},
|
||
"semantic": {
|
||
"success": "#4EBE96",
|
||
"successVariable": "--color-semantic-success",
|
||
"successLight": "#1A2924",
|
||
"successDescription": "Teal - positive values, confirmations, gains",
|
||
"warning": "#D2D714",
|
||
"warningVariable": "--color-semantic-warning",
|
||
"warningLight": "#262618",
|
||
"error": "#FF5C5C",
|
||
"errorVariable": "--color-semantic-error",
|
||
"errorLight": "#2A1A1A",
|
||
"errorDescription": "Soft red - negative values, errors, losses",
|
||
"info": "#479FFA",
|
||
"infoVariable": "--color-semantic-info",
|
||
"infoLight": "#1A2230"
|
||
},
|
||
"border": {
|
||
"default": "#232323",
|
||
"defaultVariable": "--color-border-default",
|
||
"defaultDescription": "Subtle dark border for card definition",
|
||
"focus": "#D6D876",
|
||
"focusVariable": "--color-border-focus",
|
||
"focusDescription": "Yellow accent ring for focused elements"
|
||
},
|
||
"shadows": {
|
||
"note": "Shadows are deeper/stronger in dark mode but cards primarily use borders for definition.",
|
||
"sm": "0 1px 2px 0 rgba(0, 0, 0, 0.6)",
|
||
"md": "0 4px 6px -1px rgba(0, 0, 0, 0.7)",
|
||
"lg": "0 10px 15px -3px rgba(0, 0, 0, 0.8)",
|
||
"xl": "0 20px 25px -5px rgba(0, 0, 0, 0.9)",
|
||
"focus": "0 0 0 2px rgba(230, 231, 163, 0.2)"
|
||
}
|
||
}
|
||
},
|
||
|
||
"implementationNotes": {
|
||
"css": [
|
||
"Use CSS custom properties (variables) for all colors - never hardcode color values",
|
||
"Prefer Tailwind CSS utility classes with CSS variables: bg-[var(--color-background-primary)]",
|
||
"Use rem units for typography, px for precise elements like borders",
|
||
"Import styles.css which defines all theme variables"
|
||
],
|
||
"themeSwitching": {
|
||
"darkMode": "Add 'dark' class to <html> element",
|
||
"colorTheme": "Add data-theme attribute to <html> element (e.g., data-theme=\"dusk\")",
|
||
"storage": "Persist theme preference in localStorage",
|
||
"systemPreference": "Respect prefers-color-scheme media query for initial mode"
|
||
},
|
||
"react": [
|
||
"Create reusable components for each component type",
|
||
"Use variant props for different styles (e.g., variant='primary')",
|
||
"Implement with shadcn/ui component patterns",
|
||
"Use useTheme hook for theme management"
|
||
],
|
||
"tailwindConfig": {
|
||
"extend": {
|
||
"colors": "Reference CSS variables: primary: 'var(--color-background-primary)'",
|
||
"borderRadius": "Map to --radius-* tokens",
|
||
"fontFamily": "Set Inter as default sans, JetBrains Mono for mono",
|
||
"boxShadow": "Reference --shadow-* variables"
|
||
}
|
||
},
|
||
"cssVariableMap": {
|
||
"backgrounds": [
|
||
"--color-background-primary",
|
||
"--color-background-secondary",
|
||
"--color-background-neutral"
|
||
],
|
||
"surfaces": [
|
||
"--color-surface-card",
|
||
"--color-surface-elevated",
|
||
"--color-surface-overlay"
|
||
],
|
||
"text": [
|
||
"--color-text-primary",
|
||
"--color-text-secondary",
|
||
"--color-text-tertiary",
|
||
"--color-text-inverse"
|
||
],
|
||
"accent": [
|
||
"--color-accent-primary",
|
||
"--color-accent-primary-hover",
|
||
"--color-accent-primary-light"
|
||
],
|
||
"semantic": [
|
||
"--color-semantic-success",
|
||
"--color-semantic-success-light",
|
||
"--color-semantic-warning",
|
||
"--color-semantic-warning-light",
|
||
"--color-semantic-error",
|
||
"--color-semantic-error-light",
|
||
"--color-semantic-info",
|
||
"--color-semantic-info-light"
|
||
],
|
||
"borders": [
|
||
"--color-border-default",
|
||
"--color-border-focus"
|
||
],
|
||
"shadows": [
|
||
"--shadow-sm",
|
||
"--shadow-md",
|
||
"--shadow-lg",
|
||
"--shadow-xl",
|
||
"--shadow-focus"
|
||
],
|
||
"radius": [
|
||
"--radius-sm",
|
||
"--radius-md",
|
||
"--radius-lg",
|
||
"--radius-xl",
|
||
"--radius-2xl",
|
||
"--radius-3xl",
|
||
"--radius-full"
|
||
]
|
||
}
|
||
}
|
||
}
|