From 678760b4c301376c5ceff31d6fa489285267d31f Mon Sep 17 00:00:00 2001 From: Tajudeen Date: Fri, 12 Jun 2026 03:54:40 +0100 Subject: [PATCH] chore: remove the docs/ folder The docs/ folder held only internal modernization tracking + comparison notes (MODERNIZATION-*, NEXT-SESSION-PROMPT, PHASE2-WIRING-PLAN, the comparison docs), not product documentation. Removing it from the repo; the content remains in git history. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...E-Model-Support-Code-Editing-Comparison.md | 107 --- docs/CortexIDE-vs-Other-AI-Editors.md | 546 -------------- docs/MODERNIZATION-BASELINE.md | 663 ----------------- docs/MODERNIZATION-HANDOFF.md | 264 ------- docs/NEXT-SESSION-PROMPT.md | 74 -- docs/PHASE2-WIRING-PLAN.md | 669 ------------------ 6 files changed, 2323 deletions(-) delete mode 100644 docs/CortexIDE-Model-Support-Code-Editing-Comparison.md delete mode 100644 docs/CortexIDE-vs-Other-AI-Editors.md delete mode 100644 docs/MODERNIZATION-BASELINE.md delete mode 100644 docs/MODERNIZATION-HANDOFF.md delete mode 100644 docs/NEXT-SESSION-PROMPT.md delete mode 100644 docs/PHASE2-WIRING-PLAN.md diff --git a/docs/CortexIDE-Model-Support-Code-Editing-Comparison.md b/docs/CortexIDE-Model-Support-Code-Editing-Comparison.md deleted file mode 100644 index e8cf9f8e6ac3..000000000000 --- a/docs/CortexIDE-Model-Support-Code-Editing-Comparison.md +++ /dev/null @@ -1,107 +0,0 @@ -# CortexIDE Model Support & Code Editing Capabilities Comparison - -> **⚠️ Accuracy notice (under correction — `modernize-agentic-editor-foundation`).** -> A code audit found several claims in this document were overstated or wrong. Corrections are -> being applied; until this notice is removed, treat the following as ground truth and see -> [`docs/MODERNIZATION-BASELINE.md`](./MODERNIZATION-BASELINE.md): -> - **Tree-sitter / "semantic" / vector RAG is NOT working today.** AST symbol extraction is -> currently non-functional; retrieval is **lexical (BM25) only**. The vector store (Qdrant/Chroma) -> is **experimental, off by default, and needs an embedding provider that is not yet bundled**. -> - **Rollback / auto-stash is experimental and opt-in**, not a general safety net (being hardened). -> - **Apply is not yet atomic at the disk level** (hardening in progress). -> - **Performance percentages previously stated here were never measured** and have been removed. -> -> "✅ verified in code" annotations below mean "code exists", not "feature works end-to-end". - -## Table 1: Model Support - -| Capability / Model | CortexIDE | Cursor | Windsurf | Continue.dev | Void | Code Proof (for CortexIDE) | Notes | -|-------------------|-----------|--------|----------|--------------|------|----------------------------|-------| -| **Local Ollama** | ✅ Yes | ⚠️ Limited | ❌ No | ✅ Yes | ⚠️ Limited | `modelCapabilities.ts:1174-1309`, `sendLLMMessage.impl.ts:1403-1407` | Full support with auto-detection, model listing, FIM support. Ollama is OpenAI-compatible. | -| **Local vLLM** | ✅ Yes | ❌ No | ❌ No | ❓ Unknown | ❌ No | `modelCapabilities.ts:1261-1276`, `sendLLMMessage.impl.ts:1418-1422` | OpenAI-compatible endpoint support with reasoning content parsing. | -| **Local LM Studio** | ✅ Yes | ❌ No | ❌ No | ❓ Unknown | ❌ No | `modelCapabilities.ts:1278-1292`, `sendLLMMessage.impl.ts:1434-1439` | OpenAI-compatible with model listing. Note: FIM may not work due to missing suffix parameter. | -| **Local OpenAI-compatible (LiteLLM / FastAPI / localhost)** | ✅ Yes | ❌ No | ❌ No | ⚠️ Limited | ❌ No | `modelCapabilities.ts:1311-1342`, `sendLLMMessage.impl.ts:1408-1412,1440-1444` | Supports any OpenAI-compatible endpoint. Auto-detects localhost for connection pooling. | -| **Remote OpenAI** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `modelCapabilities.ts:74-84`, `sendLLMMessage.impl.ts:1383-1387` | Full support including reasoning models (o1, o3). | -| **Remote Anthropic** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `modelCapabilities.ts:85-93`, `sendLLMMessage.impl.ts:1378-1382` | Full Claude support including Claude 3.7/4 reasoning models. | -| **Remote Mistral** | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | ❌ No | `modelCapabilities.ts:45-47`, `sendLLMMessage.impl.ts:1398-1402` | OpenAI-compatible with native FIM support. | -| **Remote Gemini** | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | ❌ No | `modelCapabilities.ts:100-107`, `sendLLMMessage.impl.ts:1393-1397` | Native Gemini API implementation. | -| **MCP tools** | ✅ Yes | ✅ Yes | ❓ Unknown | ❓ Unknown | ⚠️ Limited | `mcpChannel.ts:48-455`, `mcpService.ts:42-118`, `chatThreadService.ts:2118-2443` | Full MCP server support with stdio, HTTP, and SSE transports. Tool calling integrated in chat. | -| **Custom endpoints** | ✅ Yes | ⚠️ Limited | ❓ Unknown | ⚠️ Limited | ❌ No | `modelCapabilities.ts:1311-1326` | OpenAI-compatible endpoint support with custom headers. | -| **Model routing engine** | ✅ Yes | ⚠️ Limited | ❓ Unknown | ❓ Unknown | ❌ No | `modelRouter.ts:139-533` | Task-aware intelligent routing with quality tier estimation, context-aware selection, fallback chains. | -| **Local-first mode** | ✅ Yes | ❌ No | ❌ No | ⚠️ Limited | ❌ No | `modelRouter.ts:193-197`, `cortexideGlobalSettingsConfiguration.ts:25-30` | Setting to prefer local models with cloud fallback. Heavy bias toward local models in scoring. | -| **Privacy mode** | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No | `modelRouter.ts:173-190`, `cortexideStatusBar.ts:190-230` | Routes only to local models when privacy required (e.g., images/PDFs). Offline detection and status indicator. | -| **Warm-up system** | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No | `modelWarmupService.ts:33-141`, `editCodeService.ts:1441-1450` | Background warm-up for local models (90s cooldown). Reduces first-request latency for Ctrl+K/Apply. | -| **SDK pooling / connection reuse** | ✅ Yes | ❓ Unknown | ❓ Unknown | ❓ Unknown | ❌ No | `sendLLMMessage.impl.ts:59-162` | Client caching for local providers (Ollama, vLLM, LM Studio, localhost). HTTP keep-alive and connection pooling. | -| **Streaming for Chat** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `sendLLMMessage.impl.ts:582-632`, `chatThreadService.ts:2937-2983` | Full streaming with first-token timeout (10s local, 30s remote). Partial results on timeout. | -| **Streaming for FIM autocomplete** | ✅ Yes | ✅ Yes | ❓ Unknown | ❓ Unknown | ⚠️ Limited | `sendLLMMessage.impl.ts:331-450`, `autocompleteService.ts:853-877` | Streaming FIM for local models (Ollama, vLLM, OpenAI-compatible). Incremental UI updates. | -| **Streaming for Apply** | ✅ Yes | ✅ Yes | ✅ Yes | ❓ Unknown | ⚠️ Limited | `editCodeService.ts:1392-1634` | Streaming rewrite with writeover stream. Supports both full rewrite and search/replace modes. | -| **Streaming for Composer** | ✅ Yes | ✅ Yes | ✅ Yes | ❓ Unknown | ❌ No | `composerPanel.ts:56-1670`, `chatEditingSession.ts:450-513` | Streaming edits with diff visualization. Multi-file editing support. | -| **Streaming for Agent mode** | ✅ Yes | ✅ Yes | ❓ Unknown | ❓ Unknown | ⚠️ Limited | `chatThreadService.ts:2448-3419` | Streaming with tool orchestration. Step-by-step execution with checkpoints. | - -## Table 2: Code-Editing Capabilities - -| Capability / Model | CortexIDE | Cursor | Windsurf | Continue.dev | Void | Code Proof (for CortexIDE) | Notes | -|-------------------|-----------|--------|----------|--------------|------|----------------------------|-------| -| **Ctrl+K quick edit** | ✅ Yes | ✅ Yes | ✅ Yes | ❓ Unknown | ⚠️ Limited | `quickEditActions.ts:45-84`, `editCodeService.ts:1465-1489` | Inline edit with FIM. Supports prefix/suffix context. Local model optimizations. | -| **Apply (rewrite)** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `editCodeService.ts:1176-1201`, `prompts.ts:737-761` | Full file rewrite with local model code pruning. Supports fast apply (search/replace) for large files. | -| **Multi-file composer** | ✅ Yes | ✅ Yes | ✅ Yes | ❓ Unknown | ❌ No | `composerPanel.ts:56-1670`, `editCodeService.ts:186-802` | Multi-file editing with scope management. Auto-discovery in agent mode. | -| **Agent mode** | ✅ Yes | ✅ Yes | ❓ Unknown | ❓ Unknown | ⚠️ Limited | `chatThreadService.ts:2448-3419`, `cortexideSettingsTypes.ts:455` | Plan generation, tool orchestration, step-by-step execution. Maximum iteration limits to prevent loops. | -| **Search & replace AI** | ✅ Yes | ✅ Yes | ❓ Unknown | ❓ Unknown | ❌ No | `quickEditActions.ts:215-231`, `prompts.ts:909-960` | AI-powered search/replace with minimal patch generation. Supports fuzzy matching. | -| **Git commit message AI** | ✅ Yes | ⚠️ Limited | ❓ Unknown | ❓ Unknown | ❌ No | `cortexideSCMService.ts:72-125`, `prompts.ts:1095-1167` | Generates commit messages from git diff, stat, branch, and log. Local model optimizations. | -| **Inline autocomplete (FIM)** | ✅ Yes | ✅ Yes | ✅ Yes | ❓ Unknown | ⚠️ Limited | `autocompleteService.ts:278-1014`, `convertToLLMMessageService.ts:1737-1813` | Fill-in-middle with streaming. Token caps for local models (1,000 tokens). Smart prefix/suffix truncation. | -| **Code diff viewer** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `editCodeService.ts:2223-2289`, `codeBlockPart.ts:553-887` | Diff visualization with accept/reject. Multi-diff editor support. | -| **Chat → Plan → Diff → Apply pipeline** | ✅ Yes | ✅ Yes | ❓ Unknown | ❓ Unknown | ⚠️ Limited | `chatThreadService.ts:2448-3419`, `composerPanel.ts:1420-1560` | Workflow: agent generates plan, creates diffs, user reviews and applies. _(Rollback is experimental/opt-in — see notice.)_ | -| **Tree-sitter based RAG indexing** | ⚠️ Experimental (not working) | ❌ No | ❓ Unknown | ❌ No | ❌ No | `treeSitterService.ts`, `repoIndexerService.ts` | AST symbol extraction is currently non-functional; retrieval falls back to lexical **BM25** only. TODO: fix in Phase 4 (real RAG). | -| **Cross-file context** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `repoIndexerService.ts:868-1155`, `composerPanel.ts:1076-1144` | Hybrid BM25 + vector search. Symbol relationship indexing. Auto-discovery in agent mode. | -| **Auto-stashing + rollback** | ⚠️ Experimental / opt-in | ❓ Unknown | ❓ Unknown | ❓ Unknown | ❌ No | `gitAutoStashService.ts`, `rollbackSnapshotService.ts`, `composerPanel.ts` | Git auto-stash before multi-file Composer applies (on by default); snapshot rollback is opt-in (`cortexide.safety.rollback.enable`, default off) and only covers the Composer "Apply All" path — not a general safety net. Being hardened in Phase 1. | -| **Safe-apply (guardrails)** | ✅ Yes | ⚠️ Limited | ❓ Unknown | ❓ Unknown | ❌ No | `editCodeService.ts:1167-1172`, `toolsService.ts:570-602` | Pre-apply validation. Conflict detection. Stream state checking to prevent concurrent edits. | -| **Partial results on timeout** | ✅ Yes | ❓ Unknown | ❓ Unknown | ❓ Unknown | ❌ No | `sendLLMMessage.impl.ts:585-614` | Returns partial text on timeout (20s local, 120s remote). Prevents loss of generated content. | -| **Prompt optimization for local edit flows** | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No | `prompts.ts:737-739`, `editCodeService.ts:1453-1481` | Minimal system messages for local models. Code pruning (removes comments, blank lines). Reduces token usage. | -| **Token caps for edit flows** | ✅ Yes | ❓ Unknown | ❓ Unknown | ❓ Unknown | ❌ No | `sendLLMMessage.impl.ts:182-196`, `convertToLLMMessageService.ts:1761-1812` | Feature-specific caps: Autocomplete (96 tokens), Ctrl+K/Apply (200 tokens). Prevents excessive generation. | -| **Prefix/suffix truncation** | ✅ Yes | ❓ Unknown | ❓ Unknown | ❓ Unknown | ❌ No | `convertToLLMMessageService.ts:1767-1812` | Smart truncation at line boundaries. Prioritizes code near cursor. Max 20,000 chars per prefix/suffix. | -| **Timeout logic** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `sendLLMMessage.impl.ts:586-628`, `editCodeService.ts:277-303` | First-token timeout (10s local, 30s remote). Overall timeout (20s local, 120s remote). Feature-specific timeouts. | -| **Local-model edit acceleration** | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No | `editCodeService.ts:1441-1450`, `modelWarmupService.ts:61-92` | Warm-up system reduces first-request latency. Code pruning and minimal prompts. Connection pooling. | -| **File-scoped reasoning** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Limited | `editCodeService.ts:1392-1634` | Full file context in Apply. Prefix/suffix context in Ctrl+K. Smart context selection. | -| **Multi-model selection per feature** | ✅ Yes | ⚠️ Limited | ❓ Unknown | ⚠️ Limited | ❌ No | `cortexideSettingsTypes.ts:425-444` | Per-feature model selection: Chat, Autocomplete, Ctrl+K, Apply, Composer, Agent, SCM. Independent routing. | -| **Settings-based routing (local-first, privacy, etc.)** | ✅ Yes | ❌ No | ❌ No | ⚠️ Limited | ❌ No | `modelRouter.ts:173-197`, `cortexideGlobalSettingsConfiguration.ts:25-30` | Privacy mode (local-only), local-first mode (prefer local), quality-based routing. Context-aware selection. | - -## Legend - -- ✅ **Yes** - Feature confirmed and verified -- ⚠️ **Limited** - Partial support or basic implementation -- ❌ **No** - Feature not available -- ❓ **Unknown** - Cannot be verified from public sources - -## Key Differentiators - -### Model Support -1. **Comprehensive Local Model Support**: CortexIDE uniquely supports Ollama, vLLM, LM Studio, and any OpenAI-compatible localhost endpoint with full feature parity (FIM, streaming, tool calling). -2. **Warm-up System**: Only CortexIDE implements background model warm-up to reduce first-request latency for local models. -3. **SDK Connection Pooling**: Unique connection reuse for local providers, reducing TCP handshake overhead. -4. **Privacy Mode**: True privacy mode that routes only to local models when sensitive data (images/PDFs) is present. - -### Code Editing -1. **Codebase indexing**: CortexIDE ships a lexical **BM25** repo indexer that is queried on every turn. _(Tree-sitter AST/semantic indexing is experimental and not functional yet — see Phase 4.)_ -2. **Local Model Optimizations**: Unique prompt optimization, code pruning, and token caps specifically designed for local model performance. -3. **Smart Truncation**: Line-boundary aware prefix/suffix truncation that prioritizes code near cursor. -4. **Partial Results on Timeout**: Returns partial generated content on timeout instead of failing completely. -5. **Per-Feature Model Selection**: Independent model selection for each feature (autocomplete vs Ctrl+K vs chat), enabling optimal model per task. - -## Performance Implications - -### Local Model Optimizations -- **Warm-up System**: Pre-warms local models with a background 1-token request to reduce first-request latency (`modelWarmupService.ts`). _(Latency improvement not yet measured; no percentage is claimed.)_ -- **Code Pruning**: Trims comments/blank lines from local-model context to reduce token usage (`convertToLLMMessageService.ts`). _(Reduction not yet measured; no percentage is claimed.)_ -- **Token Caps**: Prevents excessive generation, reducing latency for autocomplete (96 tokens) and quick edits (200 tokens) -- **Connection Pooling**: Eliminates TCP handshake overhead for localhost requests - -### Timeout Handling -- **First Token Timeout**: 10s for local models prevents hanging on slow models -- **Partial Results**: Preserves generated content even on timeout, improving UX -- **Feature-Specific Timeouts**: Different timeouts per feature optimize for task requirements - -### RAG Performance -- **Codebase Indexing**: lexical BM25 retrieval today _(tree-sitter symbol extraction is experimental/non-functional — Phase 4)_ -- **Hybrid Search**: BM25 + vector search provides better relevance than either alone -- **Query Caching**: LRU cache (200 queries, 5min TTL) reduces repeated computation - diff --git a/docs/CortexIDE-vs-Other-AI-Editors.md b/docs/CortexIDE-vs-Other-AI-Editors.md deleted file mode 100644 index 37473889520b..000000000000 --- a/docs/CortexIDE-vs-Other-AI-Editors.md +++ /dev/null @@ -1,546 +0,0 @@ -# CortexIDE vs. Other AI Code Editors - -A factual comparison between CortexIDE and major AI code editors: Cursor, Antigravity, Void, Continue.dev, Claude Code, and Windsurf. - -This comparison is based on: -- **CortexIDE**: Direct code verification from the repository -- **Competitors**: Public information from official websites, documentation, and announcements -- **Unknown**: Marked when information cannot be verified from public sources - -> **⚠️ Accuracy notice (under correction — `modernize-agentic-editor-foundation`).** -> An audit found that "verified in code" here often meant "code exists", not "feature works". -> Several CortexIDE entries below were overstated and are being corrected. Ground truth until this -> notice is removed (see [`docs/MODERNIZATION-BASELINE.md`](./MODERNIZATION-BASELINE.md)): -> - **"Enterprise-Grade RAG" / tree-sitter / vector store is NOT working today** — retrieval is -> lexical **BM25 only**; AST extraction is non-functional and the vector store is experimental, -> off by default, and needs an embedding provider that is not yet bundled. (Phase 4.) -> - **Audit log + rollback are experimental/opt-in**, not a delivered enterprise guarantee. (Phase 1.) -> - **Apply is not yet atomic; "read-only" mode is not yet enforced below the prompt layer** — both -> are being fixed in Phase 1. Do not represent these as safety guarantees yet. -> - **Competitor rows may be stale** (e.g. Claude Code *does* support MCP). Treat competitor columns -> as "best-effort, may be out of date", not authoritative. - -## Quick Comparison Table - -| Feature | CortexIDE | Cursor | Antigravity | Void | Continue.dev | Claude Code | Windsurf | -|---------|-----------|--------|-------------|------|--------------|-------------|----------| -| **Open Source** | ✅ Yes (verified in code: `product.json`) | ❌ No | ❌ No | ⚠️ Source-available | ❌ No | ❌ No | ❌ No | -| **Local Models** | ✅ Yes (verified in code: `modelCapabilities.ts`, `sendLLMMessage.impl.ts`) | ⚠️ Limited | ❌ No | ⚠️ Limited | ✅ Yes | ❌ No | ❌ No | -| **Multi-Provider Support** | ✅ Yes (verified in code: `modelCapabilities.ts`) | ✅ Yes | ❓ Unknown | ❌ No | ✅ Yes | ❌ No | ❓ Unknown | -| **Fully Offline Mode** | ✅ Yes (verified in code: `modelRouter.ts`, `cortexideStatusBar.ts`) | ❌ No | ❌ No | ❌ No | ❌ No | ❌ No | ❌ No | -| **Enterprise On-Prem Installation** | ❓ Unknown | ❌ No | ❌ No | ❓ Unknown | ❌ No | ❌ No | ❌ No | -| **Multi-Model Routing** | ✅ Yes (verified in code: `modelRouter.ts`) | ✅ Yes | ❓ Unknown | ❌ No | ❓ Unknown | ❌ No | ❓ Unknown | -| **RAG / Codebase Indexing** | ✅ Yes (verified in code: `repoIndexerService.ts`, `treeSitterService.ts`) | ✅ Yes | ❓ Unknown | ❌ No | ✅ Yes | ❌ No | ❓ Unknown | -| **Chat → Plan → Diff → Apply** | ✅ Yes (verified in code: `chatThreadService.ts`, `editCodeService.ts`) | ✅ Yes | ❓ Unknown | ⚠️ Limited | ❓ Unknown | ⚠️ Limited | ❓ Unknown | -| **Multi-File Editing** | ✅ Yes (verified in code: `editCodeService.ts`) | ✅ Yes | ❓ Unknown | ⚠️ Limited | ❓ Unknown | ⚠️ Limited | ❓ Unknown | -| **Native MCP Tool Calling** | ✅ Yes (verified in code: `mcpChannel.ts`, `mcpService.ts`) | ✅ Yes | ❓ Unknown | ⚠️ Limited | ❓ Unknown | ❌ No | ❓ Unknown | -| **FIM / Code Completion** | ✅ Yes (verified in code: `autocompleteService.ts`, `sendLLMMessage.impl.ts`) | ✅ Yes | ❓ Unknown | ⚠️ Limited | ❓ Unknown | ❌ No | ❓ Unknown | -| **Agent Mode** | ✅ Yes (verified in code: `chatThreadService.ts`) | ✅ Yes | ❓ Unknown | ⚠️ Limited | ❓ Unknown | ❌ No | ❓ Unknown | -| **Audit Log + Rollback** | ⚠️ Experimental / opt-in (`auditLogService.ts`, `rollbackSnapshotService.ts`; both off by default) | ❓ Unknown | ❓ Unknown | ❌ No | ❓ Unknown | ❓ Unknown | ❓ Unknown | -| **Privacy Mode / No Telemetry** | ✅ Yes (verified in code: `telemetryUtils.ts`, `cortexideStatusBar.ts`) | ✅ Yes | ❓ Unknown | ❌ No | ❓ Unknown | ❓ Unknown | ❓ Unknown | -| **Installer Packages (Win/Mac/Linux)** | ✅ Yes (verified in code: `product.json`, build configs) | ✅ Yes | ❓ Unknown | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | -| **Extensibility (Custom tools/scripts/agents)** | ✅ Yes (verified in code: MCP tool calling, custom providers) | ✅ Yes | ❓ Unknown | ⚠️ Limited | ❓ Unknown | ❌ No | ❓ Unknown | -| **Model Support Breadth** | ✅ Yes (verified in code: `modelCapabilities.ts` - 15+ providers) | ✅ Yes | ❓ Unknown | ⚠️ Limited | ⚠️ Limited | ❌ No | ⚠️ Limited | -| **Vision/Multimodal Support** | ✅ Yes (verified in code: `modelRouter.ts`, `imageQARegistryContribution.ts`) | ✅ Yes | ❓ Unknown | ❌ No | ❓ Unknown | ✅ Yes | ❓ Unknown | -| **Reasoning Models Support** | ✅ Yes (verified in code: `modelCapabilities.ts`) | ✅ Yes | ❓ Unknown | ❌ No | ❓ Unknown | ❓ Unknown | ❓ Unknown | -| **JSON/Structured Output Handling** | ❓ Unknown | ❓ Unknown | ❓ Unknown | ❌ No | ❓ Unknown | ❓ Unknown | ❓ Unknown | -| **Customizable UI** | ✅ Yes (VS Code base) | ✅ Yes | ❓ Unknown | ✅ Yes | ✅ Yes (VS Code extension) | ❌ No | ❓ Unknown | -| **Cost / Licensing** | ✅ Open Source (MIT) | 💰 Proprietary | 💰 Proprietary | ⚠️ Source-available | ✅ Free/Open Source | 💰 Proprietary | 💰 Proprietary | - -**Legend:** -- ✅ Yes - Feature confirmed -- ❌ No - Feature not available -- ⚠️ Limited - Partial support -- ❓ Unknown - Cannot be verified from public sources -- 💰 Proprietary - Commercial licensing - -## Feature-by-Feature Breakdown - -### Open Source - -**CortexIDE**: ✅ **Yes** - MIT License (verified in `product.json`). Full source code available on GitHub. - -**Cursor**: ❌ **No** - Proprietary, closed-source. - -**Antigravity**: ❌ **No** - Proprietary, closed-source. - -**Void**: ⚠️ **Source-available** - Not fully open source, but source code is available. - -**Continue.dev**: ❌ **No** - While the extension is open source, it's built on VS Code (proprietary). - -**Claude Code**: ❌ **No** - Proprietary, closed-source. - -**Windsurf**: ❌ **No** - Proprietary, closed-source. - -### Local Models - -**CortexIDE**: ✅ **Yes** - Comprehensive local model support verified in code: -- **Ollama** (verified in `modelCapabilities.ts:1174-1309`) -- **vLLM** (verified in `modelCapabilities.ts:1261-1276`) -- **LM Studio** (verified in `modelCapabilities.ts:1278-1292`) -- **OpenAI-compatible endpoints** (verified in `modelCapabilities.ts:1311-1326`) -- Auto-detection and model listing (verified in `sendLLMMessage.impl.ts`) - -**Cursor**: ⚠️ **Limited** - Some local model support, but primarily cloud-focused. - -**Antigravity**: ❌ **No** - Cloud-first architecture, no local model support. - -**Void**: ⚠️ **Limited** - Basic local model support, primarily through Ollama. - -**Continue.dev**: ✅ **Yes** - Good local model support, works with Ollama and other local providers. - -**Claude Code**: ❌ **No** - Cloud-only, no local model support. - -**Windsurf**: ❌ **No** - Cloud-first, no local model support. - -### Multi-Provider Support - -**CortexIDE**: ✅ **Yes** - Extensive multi-provider support verified in `modelCapabilities.ts`: -- OpenAI, Anthropic, xAI, Gemini, DeepSeek, Groq, Mistral -- OpenRouter, Ollama, vLLM, LM Studio -- OpenAI-compatible, LiteLLM, Google Vertex, Microsoft Azure, AWS Bedrock -- Total: 15+ providers - -**Cursor**: ✅ **Yes** - Supports multiple providers (OpenAI, Anthropic, etc.). - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ❌ **No** - Limited to specific providers, no multi-provider routing. - -**Continue.dev**: ✅ **Yes** - Supports multiple providers through configuration. - -**Claude Code**: ❌ **No** - Claude-only (Anthropic models). - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Fully Offline Mode - -**CortexIDE**: ✅ **Yes** - Verified in code: -- Privacy mode routing to local models only (verified in `modelRouter.ts:173-190`) -- Offline detection and privacy indicator (verified in `cortexideStatusBar.ts:190-230`) -- Local-first AI mode (verified in `modelRouter.ts:193-197`) - -**Cursor**: ❌ **No** - Requires cloud connection for most features. - -**Antigravity**: ❌ **No** - Cloud-first, requires internet connection. - -**Void**: ❌ **No** - Limited offline capabilities. - -**Continue.dev**: ❌ **No** - VS Code extension, requires VS Code (which may need internet). - -**Claude Code**: ❌ **No** - Cloud-only service. - -**Windsurf**: ❌ **No** - Cloud-first architecture. - -### Multi-Model Routing - -**CortexIDE**: ✅ **Yes** - Intelligent task-aware routing verified in `modelRouter.ts`: -- Task-aware model selection (verified in `modelRouter.ts:139-533`) -- Quality tier estimation (verified in `modelRouter.ts:593-609`) -- Context-aware routing (verified in `modelRouter.ts:762-1394`) -- Fallback chains and speculative escalation (verified in `modelRouter.ts:436-449`) - -**Cursor**: ✅ **Yes** - Supports model routing and selection. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ❌ **No** - No intelligent routing, manual model selection. - -**Continue.dev**: ❓ **Unknown** - Cannot verify routing capabilities. - -**Claude Code**: ❌ **No** - Single model provider. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### RAG / Codebase Indexing - -**CortexIDE**: ⚠️ **Partial** - Lexical indexing works; semantic/vector indexing does not yet: -- ✅ Lexical **BM25** retrieval, queried on every turn (`repoIndexerService.ts`) — this is what actually runs today -- ⚠️ Tree-sitter AST parsing (`treeSitterService.ts`) — _experimental, currently non-functional_ (Phase 4) -- ⚠️ Hybrid BM25 + vector search (`repoIndexerService.ts`) — _code path exists but never activates without an embedding provider (none bundled)_ -- ⚠️ Vector store (Qdrant, Chroma) (`vectorStore.ts`) — _experimental, off by default (`cortexide.rag.vectorStore`), needs embeddings_ - -**Cursor**: ✅ **Yes** - Codebase indexing and context retrieval (semantic embeddings). - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ❌ **No** - No RAG or codebase indexing. - -**Continue.dev**: ✅ **Yes** - Good RAG pipeline for codebase context. - -**Claude Code**: ❌ **No** - No codebase indexing. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Chat → Plan → Diff → Apply - -**CortexIDE**: ✅ **Yes** - Complete workflow verified in code: -- Agent mode with plan generation (verified in `chatThreadService.ts:2448-3419`) -- Plan tracking and step management (verified in `chatThreadServiceTypes.ts:50-69`) -- Diff visualization and editing (verified in `editCodeService.ts:2223-2392`) -- Apply pipeline with rollback (verified in `composerPanel.ts:1420-1560`) - -**Cursor**: ✅ **Yes** - Composer feature with plan → diff → apply workflow. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ⚠️ **Limited** - Basic chat and editing, no structured plan workflow. - -**Continue.dev**: ❓ **Unknown** - Cannot verify structured plan workflow. - -**Claude Code**: ⚠️ **Limited** - Inline editing, no full plan → apply workflow. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Multi-File Editing - -**CortexIDE**: ✅ **Yes** - Multi-file editing verified in `editCodeService.ts`: -- Batch file operations (verified throughout `editCodeService.ts`) -- Multi-file diff management (verified in `editCodeService.ts:186-802`) - -**Cursor**: ✅ **Yes** - Multi-file editing support. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ⚠️ **Limited** - Basic multi-file support. - -**Continue.dev**: ❓ **Unknown** - Cannot verify multi-file editing capabilities. - -**Claude Code**: ⚠️ **Limited** - Primarily single-file inline editing. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Native MCP Tool Calling - -**CortexIDE**: ✅ **Yes** - Native MCP support verified in code: -- MCP server management (verified in `mcpChannel.ts:48-455`) -- Tool calling infrastructure (verified in `mcpService.ts:325-331`) -- MCP tool integration in chat (verified in `chatThreadService.ts:2118-2443`) - -**Cursor**: ✅ **Yes** - MCP tool calling support. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ⚠️ **Limited** - Basic tool calling, not full MCP support. - -**Continue.dev**: ❓ **Unknown** - Cannot verify MCP support. - -**Claude Code**: ✅ **Yes** - Claude Code supports MCP (stdio and remote servers). _(Corrected: the previous "No MCP" claim was factually wrong.)_ - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### FIM / Code Completion - -**CortexIDE**: ✅ **Yes** - FIM support verified in code: -- Fill-in-middle implementation (verified in `autocompleteService.ts:278-1014`) -- FIM message preparation (verified in `convertToLLMMessageService.ts:1737-1813`) -- Model capability detection (verified in `modelCapabilities.ts:175`) -- Streaming FIM for local models (verified in `sendLLMMessage.impl.ts:331-450`) - -**Cursor**: ✅ **Yes** - FIM code completion. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ⚠️ **Limited** - Basic autocomplete, not full FIM. - -**Continue.dev**: ❓ **Unknown** - Cannot verify FIM support. - -**Claude Code**: ❌ **No** - No FIM code completion. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Agent Mode - -**CortexIDE**: ✅ **Yes** - Agent mode verified in code: -- Agent execution loop (verified in `chatThreadService.ts:2448-3419`) -- Plan generation and tracking (verified in `chatThreadServiceTypes.ts:50-69`) -- Tool orchestration (verified in `chatThreadService.ts:2118-2443`) -- Step-by-step execution with checkpoints (verified in `chatThreadService.ts:1429-1445`) - -**Cursor**: ✅ **Yes** - Agent mode with Composer. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ⚠️ **Limited** - Basic agent capabilities. - -**Continue.dev**: ❓ **Unknown** - Cannot verify agent mode. - -**Claude Code**: ✅ **Yes** - Claude Code is a terminal-first agent. _(Corrected: the previous "No agent mode" claim was wrong.)_ - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Audit Log + Rollback - -**CortexIDE**: ⚠️ **Experimental / opt-in** - the code exists but both are off by default and not yet a delivered guarantee: -- Audit log service (`auditLogService.ts`) — opt-in via `cortexide.audit.enable` (default off) -- Rollback snapshot service (`rollbackSnapshotService.ts`) — opt-in via `cortexide.safety.rollback.enable` (default off), Composer "Apply All" path only; being hardened into durable, operation-level rollback in Phase 1 -- Automatic snapshot creation before applies (verified in `composerPanel.ts:1420-1560`) -- Git auto-stash integration (verified in `gitAutoStashService.ts`) - -**Cursor**: ❓ **Unknown** - Cannot verify audit log or rollback features. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ❌ **No** - No audit log or rollback. - -**Continue.dev**: ❓ **Unknown** - Cannot verify from public sources. - -**Claude Code**: ❌ **No** - No audit log or rollback. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Privacy Mode / No Telemetry - -**CortexIDE**: ✅ **Yes** - Privacy features verified in code: -- Privacy mode routing (verified in `modelRouter.ts:173-190`) -- Telemetry configuration (verified in `telemetryUtils.ts:95-101`) -- Privacy status indicator (verified in `cortexideStatusBar.ts:190-230`) -- Local-first AI mode (verified in `modelRouter.ts:193-197`) - -**Cursor**: ✅ **Yes** - Privacy mode available. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ❌ **No** - No privacy mode. - -**Continue.dev**: ❓ **Unknown** - Cannot verify from public sources. - -**Claude Code**: ❓ **Unknown** - Cannot verify from public sources. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Installer Packages (Win/Mac/Linux) - -**CortexIDE**: ✅ **Yes** - Installer packages verified: -- Windows identifiers (verified in `product.json:21-24`) -- macOS bundle identifier (verified in `product.json:37`) -- Linux packaging (verified in `product.json:38`, `resources/linux/`) -- Build configuration for all platforms - -**Cursor**: ✅ **Yes** - Installers for Windows, macOS, and Linux. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ✅ **Yes** - Installers available. - -**Continue.dev**: ✅ **Yes** - VS Code extension (requires VS Code). - -**Claude Code**: ❌ **No** - Web-based, no installers. - -**Windsurf**: ✅ **Yes** - Installers available. - -### Extensibility (Custom tools/scripts/agents) - -**CortexIDE**: ✅ **Yes** - Extensibility verified: -- MCP tool integration (verified in `mcpChannel.ts`, `mcpService.ts`) -- Custom provider support (verified in `modelCapabilities.ts`) -- VS Code extension API (inherited from VS Code base) - -**Cursor**: ✅ **Yes** - Extensibility through plugins and integrations. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ⚠️ **Limited** - Basic extensibility. - -**Continue.dev**: ❓ **Unknown** - Cannot verify extensibility. - -**Claude Code**: ❌ **No** - No extensibility. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Model Support Breadth - -**CortexIDE**: ✅ **Yes** - Extensive model support verified in `modelCapabilities.ts`: -- **15+ providers**: OpenAI, Anthropic, xAI, Gemini, DeepSeek, Groq, Mistral, OpenRouter, Ollama, vLLM, LM Studio, OpenAI-compatible, LiteLLM, Google Vertex, Microsoft Azure, AWS Bedrock -- **Reasoning models**: o1, o3, Claude 3.7/4, DeepSeek R1, QwQ, Qwen3, Phi-4 -- **Vision models**: GPT-4o, GPT-4.1, GPT-5 series, o-series (o1, o3, o4-mini), Claude 3.5/4, Gemini (all models), Pixtral, local VLMs -- **FIM models**: Codestral, Qwen2.5-coder, StarCoder2 - -**Cursor**: ✅ **Yes** - Wide model support. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ⚠️ **Limited** - Supports common models, not as extensive. - -**Continue.dev**: ⚠️ **Limited** - Good support but fewer providers than CortexIDE. - -**Claude Code**: ❌ **No** - Claude models only. - -**Windsurf**: ⚠️ **Limited** - Supports multiple models but fewer than CortexIDE. - -### Vision/Multimodal Support - -**CortexIDE**: ✅ **Yes** - Vision support verified in code: -- Vision-capable model detection (verified in `modelRouter.ts:1400-1417`) -- Image QA registry (verified in `imageQARegistryContribution.ts`) -- Multimodal message handling (verified in `convertToLLMMessageService.ts`) -- Supports image uploads for: GPT-4o, GPT-4.1, GPT-5 series, o-series, Claude 3.5/4, Gemini (all), Pixtral, local VLMs -- PDF upload support with text extraction and vision-based processing - -**Cursor**: ✅ **Yes** - Vision model support. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ❌ **No** - No vision support. - -**Continue.dev**: ❓ **Unknown** - Cannot verify from public sources. - -**Claude Code**: ✅ **Yes** - Claude models support vision. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -### Reasoning Models Support - -**CortexIDE**: ✅ **Yes** - Reasoning model support verified in `modelCapabilities.ts`: -- Reasoning capability detection (verified in `modelCapabilities.ts:180-194`) -- Reasoning budget/effort sliders (verified in `modelCapabilities.ts:185-188`) -- Support for o1, o3, Claude 3.7/4, DeepSeek R1, QwQ, Qwen3, Phi-4 - -**Cursor**: ✅ **Yes** - Reasoning model support. - -**Antigravity**: ❓ **Unknown** - Cannot verify from public sources. - -**Void**: ❌ **No** - No reasoning model support. - -**Continue.dev**: ❓ **Unknown** - Cannot verify from public sources. - -**Claude Code**: ❓ **Unknown** - Cannot verify reasoning model support. - -**Windsurf**: ❓ **Unknown** - Cannot verify from public sources. - -## CortexIDE's Key Differentiators - -Based on verified code, CortexIDE offers several unique advantages: - -### 1. **Open Source with Full Feature Parity** -- Complete source code available under MIT license -- No vendor lock-in -- Community-driven development - -### 2. **Comprehensive Local Model Support** -- Native support for Ollama, vLLM, and LM Studio -- Auto-detection and model listing -- Optimized streaming for local models -- Privacy-first routing to local models - -### 3. **Advanced Multi-Provider Routing** -- Task-aware intelligent routing (verified in `modelRouter.ts`) -- Quality tier estimation -- Context-aware model selection -- Fallback chains and speculative escalation -- 15+ provider support - -### 4. **Codebase RAG Pipeline** _(lexical today; semantic in progress)_ -- Lexical **BM25** retrieval, queried on every turn (working) -- ⚠️ Tree-sitter AST symbol extraction — _experimental, currently non-functional_ (Phase 4) -- ⚠️ Hybrid BM25 + vector search and Qdrant/Chroma vector store — _experimental, off by default,_ - _requires an embedding provider that is not yet bundled_ (Phase 4) - -### 5. **Audit Trail & Recovery** _(experimental / opt-in)_ -- Audit logging service (`auditLogService.ts`) — opt-in via `cortexide.audit.enable` (default off) -- Git auto-stash before multi-file Composer applies (on by default) -- ⚠️ Snapshot rollback — opt-in (`cortexide.safety.rollback.enable`, default off), Composer path only; - being hardened into a real recovery mechanism in Phase 1 - -### 6. **True Offline Mode** -- Privacy mode that routes only to local models -- Offline detection and status indicators -- Local-first AI mode -- No telemetry when privacy mode enabled - -### 7. **Advanced Agent Workflow** -- Plan generation and tracking -- Step-by-step execution with checkpoints -- Tool orchestration -- Rollback to any step - -### 8. **Extensive Model Capabilities** -- Support for reasoning models (o1, o3, Claude 3.7/4, DeepSeek R1, etc.) -- Vision/multimodal support -- FIM code completion -- Model capability detection and optimization - -## Where Each Tool Fits Best - -### CortexIDE -**Best for:** -- Developers who need open-source solutions -- Teams requiring offline/privacy-first workflows -- Organizations needing enterprise features (audit logs, rollback) -- Users wanting maximum model/provider flexibility -- Developers working with local models (Ollama, vLLM, LM Studio) -- Teams needing advanced RAG with tree-sitter indexing - -### Cursor -**Best for:** -- Developers who prefer a polished, proprietary solution -- Teams comfortable with cloud-based workflows -- Users wanting a Cursor-like experience with strong multi-file editing -- Developers who need MCP tool calling - -### Antigravity -**Best for:** -- Teams preferring cloud-first, workspace-based AI -- Users wanting automatic agent suggestions -- Organizations comfortable with proprietary solutions - -### Void -**Best for:** -- Developers who want source-available code -- Users needing basic local model support -- Simple chat-with-model workflows - -### Continue.dev -**Best for:** -- VS Code users wanting AI assistance -- Developers who prefer extension-based solutions -- Teams needing good RAG pipeline within VS Code -- Users wanting local model support in VS Code - -### Claude Code -**Best for:** -- Developers who primarily use Claude models -- Users needing inline code editing -- Teams comfortable with cloud-only solutions - -### Windsurf -**Best for:** -- Developers wanting a cloud-first AI assistant/editor hybrid -- Teams comfortable with proprietary solutions -- Users who prefer integrated AI workflows - -## Supported Models - -For a detailed list of models supported by CortexIDE, see the [Supported Models documentation](https://github.com/cortexide/cortexide/wiki/Supported-Models) (link to be added). - -CortexIDE supports 15+ providers with 100+ models, including: -- Reasoning models (o1, o3, Claude 3.7/4, DeepSeek R1, QwQ, Qwen3, Phi-4) -- Vision models (GPT-4o, GPT-4.1, GPT-5 series, o-series, Claude 3.5/4, Gemini, Pixtral, local VLMs) -- FIM models (Codestral, Qwen2.5-coder, StarCoder2) -- Local models (Ollama, vLLM, LM Studio) - - -## Conclusion - -CortexIDE stands out as the **only fully open-source AI code editor** with: -- Comprehensive local model support -- Advanced multi-provider routing -- Enterprise-grade features (audit logs, rollback) -- True offline/privacy mode -- Extensive model and provider support - -While other tools excel in specific areas (Cursor's polish, Continue.dev's VS Code integration), CortexIDE offers the most complete open-source solution with the flexibility to work with any model, any provider, and in any environment (cloud, local, or offline). - ---- - -**Last Updated**: Based on codebase analysis as of the current date. For the most up-to-date information, refer to the official documentation of each tool. - -**Note**: This comparison is based on: -- CortexIDE: Direct code verification from the repository -- Competitors: Public information from official sources -- Unknown: Marked when information cannot be verified - -If you find any inaccuracies, please [open an issue](https://github.com/cortexide/cortexide/issues/new) with corrections and sources. - - - diff --git a/docs/MODERNIZATION-BASELINE.md b/docs/MODERNIZATION-BASELINE.md deleted file mode 100644 index f0aa6233ff32..000000000000 --- a/docs/MODERNIZATION-BASELINE.md +++ /dev/null @@ -1,663 +0,0 @@ -# Modernization Baseline - -Captured at the start of the `modernize-agentic-editor-foundation` effort. This is the -ground-truth state we are measuring all phases against. Do not edit retroactively — append -phase results below instead. - -## Git - -- **Branch:** `modernize-agentic-editor-foundation` (forked from `fix/agentic-mode-cloud-failover-2026-06-05`, - which is 89 commits ahead of `main`, 0 behind — it carries the Session-11 agentic fixes). -- **Working tree at branch creation:** clean (0 uncommitted changes). - -## Versions / runtime - -- VS Code base: **1.118.1** (`package.json` `version`) -- Electron: **39.8.8** (`package.json` devDependencies) -- Node: **22.22.1** (`.nvmrc`) -- distro pin: `b85ea484c93395a77703478557a49e35ac7c0841` -- Product: `nameShort`/`nameLong` = `CortexIDE` (`product.json`) - -## Commands - -| Purpose | Command | -|---|---| -| Type check (fast) | `npm run compile-check-ts-native` → `tsgo --project ./src/tsconfig.json --noEmit --skipLibCheck` | -| Node unit tests (all) | `npm run test-node` → `mocha test/unit/node/index.js` | -| Node unit tests (cortexide subset) | `npm run test-node -- --runGlob "vs/workbench/contrib/cortexide/test/common/*.test.js"` | -| Browser unit tests | `npm run test-browser` | -| Full build | `npm run compile` (gulp) | -| React UI build | `npm run buildreact` (source = `browser/react/src2/`, **not** `src/`) | -| Fast transpile src→out | `node build/next/index.ts transpile` | - -Node test runner globs `**/test/**/*.test.js` and **excludes** `**/{browser,electron-browser,electron-main,electron-utility}/**/*.test.js`, -so node-runnable tests must live in a `test/common/` directory. - -## Test baseline (cortexide subset) - -- `npm run test-node -- --runGlob "vs/workbench/contrib/cortexide/test/common/*.test.js"` - → **214 passing, 0 failing** (108ms). - -### Known weak/placeholder tests (pass but prove nothing — tracked for Phase 1/2) - -- `test/common/rollbackSnapshotService.test.ts` — all bodies are `assert.ok(true)` placeholders. -- `test/common/autostash.flow.test.ts` — all bodies are `assert.ok(true)` placeholders. -- `test/common/applyAll.rollback.flow.test.ts` — all bodies are `assert.ok(true)` placeholders. -- `test/common/ssrfGuard.test.ts` — imports from the `browser/` layer; silently fails to compile and is never exercised (the real coverage is `test/browser/ssrfGuard.test.ts`). - -## Highest-risk untested subsystems (no direct tests at baseline) - -- `browser/chatThreadService.ts` (6,217 lines — agent loop) — **0 direct tests**. -- `browser/editCodeService.ts` (2,609 lines — apply engine) — **0 direct tests**. -- `electron-main/llmMessage/sendLLMMessage.impl.ts` (18-provider dispatch) — **0 tests**. -- `common/modelRouter.ts` (1,763 lines) — **0 tests**. -- IPC channels (`mcpChannel`, `hooksRunnerChannel`, `sendLLMMessageChannel`) — **0 tests**. - -## Config keys read by code but NOT registered at baseline (invisible in Settings UI) - -`cortexide.global.localFirstAI`, `cortexide.index.ast`, `cortexide.safety.rollback.enable`, -`cortexide.safety.rollback.maxSnapshotBytes`, `cortexide.safety.autostash.enable`, -`cortexide.safety.autostash.mode`, `cortexide.rag.vectorStore`, `cortexide.rag.vectorStoreUrl`, -`cortexide.audit.enable`, `cortexide.audit.path`, `cortexide.audit.rotationSizeMB`. -(`cortexide.secretDetection.*` IS registered via `secretDetectionConfiguration.ts`.) - -The registering contribution `cortexideGlobalSettingsConfiguration.ts` existed but was **never imported** -into `cortexide.contribution.ts`, so even `cortexide.global.localFirstAI` was unregistered. - ---- - -## Phase results (append-only) - -### Phase 0 — Stop shipping broken promises ✅ (4 commits) - -- **Config registration:** `cortexideConfigKeys.ts` (pure SSOT) + rewritten - `cortexideGlobalSettingsConfiguration.ts` now register the 11 `cortexide.*` keys services - read; the contribution is statically imported in `cortexide.contribution.ts`. Defaults match - each service's `?? fallback`; experimental/degrading features stay OFF (rag.vectorStore='none', - rollback off, audit off, ast experimental). -- **Tool count:** false "27 built-ins" → dynamic `builtinToolCount` (**35**) from - `builtinToolNames.ts`, edited in `src/` (authored source). Compile-time `Record` - exhaustiveness guard + count test prevent drift. -- **Docs:** accuracy banners on both comparison docs; removed fabricated "50-90%"/"20-40%" figures; - fixed false "Claude Code: No MCP / No agent mode"; downgraded dead tree-sitter/vector/"Enterprise-Grade - RAG" and experimental audit/rollback claims. -- **Dead code:** removed 11 orphaned files + `common/telemetry/` (re-verified 0 importers each). -- **Claim-verification test:** `phase0ClaimVerification.test.ts` (8 tests) fails if a service reads - an unregistered key or an experimental feature gets a degrading default. -- **Result:** cortexide common node tests **214 → 222 passing, 0 failing**. tsgo clean. - -**Audit corrections discovered while implementing (the audit was WRONG on these):** -- `browser/react/src/` is **NOT dead** — it is the authored source; `src2/` and `out/` are - **gitignored** build artifacts generated by `scope-tailwind`/`tsup`. (Audit debt #17 would have - deleted the real UI source.) Edit `src/`, never `src2/`. -- `common/diffComposerAudit.ts` is **LIVE** (used at runtime by `composerPanel.ts`), not dead. -- Real built-in tool count is **35**, not 27 (claimed) or 17 (audit estimate). - -### Phase 1 — Protect User Workspaces ⚠️ PARTIAL (5 commits) - -Done + tested (cortexide common subset 222 → **243 passing, 0 failing**, tsgo clean throughout): -- **#3 Gather/read-only enforced at DISPATCH** (the keystone critical bug): new pure - `common/toolPermissions.ts` (capability table + `checkToolAllowedInMode`); `_runToolCall` now - gates every call (any parse path) BEFORE validation/approval/execution. `toolPermissions.test.ts`. -- **#4 Terminal danger now BLOCKS**: new pure `common/commandRisk.ts` classifier wired into the - terminal approval gate — dangerous commands can't be auto-approved, catastrophic ones are refused. - `commandRisk.test.ts`. -- **#1 Atomic writes (partial)**: `applyEngineV2` create+edit now request temp-file+rename atomic - writes. `applyEngineV2.test.ts` asserts it via a capturing mock. -- **#6 Workspace Trust enforced at dispatch**: untrusted workspace blocks write/terminal/MCP (read - allowed); `IWorkspaceTrustManagementService` injected into `chatThreadService`. -- **#4 Terminal cwd containment**: new pure `cwdEscapesWorkspace()`; a command whose cwd escapes the - workspace can no longer be auto-approved (forces explicit approval). Multi-root aware. Tested. -- **#5 Secret redaction**: VERIFIED already implemented + secure-by-default (audit was WRONG that it - was "completely unmitigated"). `sendLLMMessageService` redacts the outbound payload across all - provider message formats; `cortexide.secretDetection.enabled` defaults true, `mode` defaults - 'redact', `block` mode honored. No code change needed. - -**Build verification (real build, not piecemeal esbuild):** -- `npm run compile-check-ts-native` (tsgo, whole project): **0 errors**. -- `npm run buildreact`: success (onboarding bundle builds with dynamic `builtinToolCount`). -- `node build/next/index.ts transpile`: 5942 files, ok. -- `test-node` cortexide common subset: **249 passing, 0 failing**. -- NOTE: earlier `tsgo` runs were wrapped in `timeout` (absent on macOS) and silently no-op'd; the - real runs above confirm 0 errors. A real transpile also surfaced + fixed a suite-crashing broken - test (`test/common/ssrfGuard.test.ts` imported the browser layer → `MouseEvent` crash; deleted). - -NOT done (DoD not met — Phase 1 is NOT complete; require core changes + LIVE app verification): -- **#1 agent-path atomic** — `editCodeService → cortexideModelService.saveModel → textFileService.save` - is still non-atomic (`save` has no atomic option; a direct atomic write there desyncs the editor's - dirty/etag state). Needs a core `textFileEditorModel` atomic-save option + a running app to verify - dirty-state behavior. **Top follow-up.** -- **#2 Durable checkpoint/rollback** — still can't recreate deleted / remove created files, doesn't - persist to disk, swallows errors (chatThreadService:5193-5298, editCodeService restore). L-effort, - entangled, needs live verification. -- These two need a build+launch+exercise loop (CDP smoke), not just unit tests, to change safely. - -### Phase 1 — LIVE agent-driven verification (2026-06-10, capable model) - -Pulled `qwen2.5-coder:7b` (Auto had been picking the weak 3B). Results: -- **Gate A (gather read-only) — PROVEN end-to-end.** `test/cortexide-smoke/gather-isolated-e2e.mjs` - (fresh profile, GATHER only, no agent follow-up): the 7B emitted a real `` tool call, - and even after **Approve & Execute** (plan executed), `pwned.txt` was **never written to disk**. - The dispatch gate blocks real model-emitted writes in gather mode. - - Earlier alarming `pwned.txt`-on-disk was **agent-mode contamination** (a reused conversation - switched gather→agent; the agent phase, where writes ARE allowed, created it). Lesson: never - reuse a chat conversation across mode switches in a safety test. -- **Gate E (settings) / config + secure defaults — PROVEN live.** `phase1-safety-verify.mjs` 26/26 - (real modules decide correctly in-renderer; keys registered; vectorStore='none', secretDetect redact). -- **Gate D (workspace trust) — logic+wiring+trusted-path verified; untrusted-block NOT live-exercised.** - The dev CLI launch **auto-trusts** the workspace (no Restricted Mode even with `CX_KEEP_TRUST=1` + - seeded `security.workspace.trust.*`). Same dispatch chokepoint as the proven gather gate. -- **Gates B/C (terminal danger / cwd) — logic+wiring verified (26/26 + artifact); not driven live** - (would need the model to emit specific terminal commands + I won't run destructive commands). -- App boots on the branch (cdp-smoke 11/11). Capable agent writes work (diagtest.txt created by 7B in - agent mode). `launch-dev.sh` gains `CX_KEEP_TRUST=1`. - -### Phase 1 #1 — agent-path atomic writes ✅ DONE (2026-06-10) - -The agent edit path (`editCodeService → cortexideModelService.saveModel → textFileService.save`) -is now atomic. Minimal opt-in core change reusing the normal save path (dirty/etag stay correct): -`ISaveOptions.atomicWrite?` → `textFileEditorModel.doSave` passes `atomic:{postfix:'.vsctmp'}` → -`saveModel` requests it, guarded by the provider's `FileAtomicWrite` capability (remote/virtual -fall back, no throw). tsgo 0 errors; unit `cortexideModelServiceSave.test.ts` (3); subset **252/0**; -LIVE E2E (`atomic-edit-e2e.mjs`, real 7B): rewrote target.txt → correct content, no `.vsctmp` leak, -editor stable. (applyEngineV2 was already atomic.) - -### Phase 1 #2 — durable checkpoint/rollback ✅ DONE + LIVE-VALIDATED (2026-06-10) - -Edit restore now PERSISTS to disk (editCodeService awaits atomic `saveModel`). New pure -`common/agentFileOps.ts` (12 unit tests) = durable per-op rollback: recreate deleted (with prior -content), remove created, restore modified; atomic writes; failures surfaced; sequential edits undo -in reverse. `chatThreadService` journals the BEFORE-state of create/delete/edit/rewrite/multi_edit at -the dispatch chokepoint and replays them on disk on a checkpoint jump (+notify on incomplete). -tsgo 0; subset **263/0**. LIVE E2E (real 7B agent): create→rollback REMOVES; delete→rollback RECREATES -with original content; edit V1→V2→rollback restores V1 ON DISK. (Lesson: a checkpoint jump no-ops -while the agent is running — wait for idle.) Documented limitations: session-scoped journal (not across -app restart); deleted-folder contents not restored; redo doesn't re-apply create/delete. - -### Phase 1 — FUNCTIONALLY COMPLETE -All 6 items implemented, unit-tested (**263 passing, 0 failing**), tsgo 0 errors, and the -safety-critical behaviours live-validated end-to-end: -- #1 atomic writes ✅ (applyEngineV2 + agent-path saveModel; live: edit persists, no temp leak) -- #2 durable rollback ✅ (create/delete/edit restore on disk — live) -- #3 gather read-only at dispatch ✅ (live: blocks a real model-emitted write) -- #4 terminal danger-block + cwd containment ✅ (logic+wiring+renderer-tested; not driven with real destructive commands) -- #5 secret redaction before LLM ✅ (verified secure-by-default, live config) -- #6 workspace trust ✅ (logic+wiring+trusted-path live; untrusted-block NOT live — dev launch auto-trusts) - -Honest residuals: gate D untrusted-block and gates B/C with real destructive commands are not -*driven* live (dev auto-trust; won't run `rm -rf`), but they share the dispatch chokepoint that IS -live-proven via the gather gate, and their decision logic is renderer-tested (26/26). - -### Phase 2 — testable agent runtime (IN PROGRESS) - -Step 1 done (zero-risk): the agent loop's pure DECISION logic is extracted into -`common/agentLoopDecisions.ts` (5 pure fns: tool-error counter, escalation trigger, loop -continuation, completion routing, compaction/overflow) with **57 unit tests** — mirroring the -inline loop behavior byte-for-byte (two known latent bugs B1/B2 preserved + pinned). NO wiring yet, -so zero runtime risk. Design came from a 7-agent mapping workflow (`.claude/phase2-map-workflow.js`) -that verified every line/constant against source. tsgo 0; subset **263 -> 320 passing, 0 failing**. - -Remaining Phase 2 (separate behavior-preserving + live-validated commits): rewire the loop to -delegate to these (Edit A tool-error cap, then compaction, then iter-cap; defer the parse-classifier -+ llmError-gate to their own PRs), then the larger module split (AgentLoopController / ToolCallParser -/ AgentPlanner / etc.) per the user's Phase 2 spec. - -### Phase 2 — wiring Edits A/D/B LANDED + live-validated (2026-06-10) - -Step 2 done: the agent loop now DELEGATES to the pure decision fns (the tested module is the code -that runs, not a parallel copy that can drift). Three behavior-preserving commits, each tsgo 0 + -subset 320/0: -- **Edit A** (`db1bbdb0abd`) tool-error cap -> `updateConsecutiveToolErrors` with - `escalationAvailable:false` (keeps `consecutiveToolErrors` at the incremented value so the - escalate-reason + halt-message strings stay byte-identical, em-dash included; `tryEscalateModel` - stays authoritative). -- **Edit D** (`53f6a12d0c0`) compaction + overflow -> `computeCompactionOverflowDecision`; de-dupes - the two dynamic `getModelCapabilities` imports into ONE `contextWindow` resolution gated by a - `capsResolved` flag (closes the only divergence: the unreachable import-throw path). IMPROVEMENT - over the plan: split into a pre-compaction `compactDecision` and a post-compaction - `overflowDecision` so the warning reflects post-compaction `promptTokens` (a single pre-compaction - call would have spuriously warned after a successful compaction). -- **Edit B** (`cac44f0039a`) iter-cap escalation gate -> `shouldEscalateModel('iterCap')`; - short-circuit is provably equivalent to the original unconditional await (tryEscalateModel returns - false at its own guard with no side effect). `isAutoMode` is out of scope here (TDZ) and ignored by - the iterCap branch, so it is passed as a literal `false`. - -**Adversarial verification (6-agent Workflow, `.../phase2-wiring-adversarial-review`):** all 6 -reviewers (per-edit control-flow/strings/tokens/scope + a whole-diff integration critic) returned -behaviorPreserving=TRUE, **zero reachable divergences**. One reviewer ran an exhaustive 9,216-combo -enumeration of the compaction/overflow inputs (0 divergences in {shouldCompact, warn, pct}); strings -verified byte-identical incl. the U+2014 em-dash; B1/B2 latent behaviors confirmed preserved. The two -flagged non-issues were a non-observable microtask/await-timing change (Edit B short-circuit) and the -redundant `overflowPct != null` guard. - -**Live validation (CDP, post-wiring build, fresh ws):** -- boot smoke `cdp-smoke.mjs` 11/11. -- HAPPY PATH: `atomic-edit-e2e.mjs` with `qwen2.5-coder:7b` in Agent mode rewrote target.txt - correctly (marker present, not empty, no .vsctmp leak) -> loop continuation + Edit A success-reset - + per-iteration Edit D/B checks all intact end-to-end. -- CAP/ESCALATION PATH: new `phase2-cap-escalation-probe.mjs` with `qwen2.5-coder:1.5b` (thrashes on a - multi-step Flask task) -> the wired cap path triggered `tryEscalateModel` live ("Switched to ..." - detected) -> the escalation wiring fires under real model thrash. (The toast does not distinguish - tool-error-cap vs iter-cap as the trigger, but a wired path fired.) - -Tests: cortexide common node subset **320 passing, 0 failing**; tsgo 0 errors throughout. - -Deferred (own reviewed PRs, per the plan): Edit C (llmError escalation gate, `nextModel`-scope -sensitive), Edit E (completion routing collapse), and the parse-classifier (function #6, -classifyToolCallFromLLMResponse). Then the larger module split (AgentLoopController / ToolCallParser -/ ToolPermissionEngine / AgentPlanner / ModelSelectionEngine / AgentContextBuilder / AgentSessionStore -/ AgentVerifier). - -### Phase 2 — Edit E investigated + DEFERRED; first module-split (ToolCallParser core) LANDED (2026-06-10) - -**Edit E (completion-routing collapse) was mapped and DEFERRED as not worth doing now.** A 4-agent -mapping workflow (`.../phase2-editE-routing-map`) produced a full terminus table of the LLM-turn block -and concluded: the genuinely valuable full-collapse (Option A) is UNSAFE because the -`interrupted`/`completionSignaled` returns sit BEFORE the consecutive-tool-error cap + plan-step -bookkeeping while the `await`/`continue` decision sits AFTER -- collapsing them into one -`classifyCompletionState` switch would reorder side effects. The safe minimal wiring (Option B) only -wraps the trivial `awaitingUserApproval ? await : continue` + the two skip flags in verbose pure-fn -calls (all other inputs hard-coded false) -- low value, added verbosity, no reliability/testability -gain. So `classifyCompletionState` (and `decideLoopContinuation`, which overlaps what A/B already -wired) stay UNWIRED by choice; they remain tested. Conclusion: the cleanly-wireable pure decisions are -all wired (A/D/B); the remaining two model routing the real loop cannot cleanly separate. - -**First module-split increment LANDED** (`a99767686cd`): extracted the agent loop's text-fallback -tool-call recognition into pure `common/toolCallRecognition.ts` (`recognizeTextToolCall`) and removed -the single-use private `_parseJSONToolCallFromText`. This is the safe core of the deferred -parse-classifier (ToolCallParser) and centralizes + TESTS the previously-untested preamble/marker-cut -logic that strips a model's hallucinated multi-tool transcript (the #1 weak/local-model robustness -hazard). Behavior-preserving (mirrors the inline block byte-for-byte: same parseTextToolCall, same -4-marker cut, same cutIdx>0/===0/===-1 preamble ternary, same toolCall build). The latent bug B1 -(unparseable would-be tool call silently treated as natural text) is PRESERVED; its deliberate fix -belongs in this module in a later tested change (documented in the module header). Verification: tsgo 0; -new `test/common/toolCallRecognition.test.ts` (10 cases) -> subset **320 -> 330 passing, 0 failing**; -adversarial review (21-input equivalence fuzz) byte-identical; LIVE cdp-smoke 11/11 + atomic-edit-e2e -with `qwen2.5-coder:7b` (which emits the tool call as TEXT) recognized + executed -> file rewritten. - -**Second module-split increment LANDED** (`7c548eb9a95`): extracted the agent loop's "should I -SYNTHESIZE a tool call from the model's prose?" GATE into pure `common/toolSynthesisDecision.ts` -(`decideToolSynthesis`); the synthesis ACTION stays inline. This finally TESTS the heuristic that most -governs weak/local-model agentic behavior (when a chatty reply auto-converts to an action): the -action/codebase/web intent word lists, the already-emitted-tool-tag suppression, the `looksFinal` -closer regex, the image-analysis carve-out, and the nAttempts/alreadyActed/file-cap gating. It is also -the synthesis machinery that is B1's runtime vector, now isolated + pinned. Behavior-preserving -(mirrors the inline outer guard + inner condition byte-for-byte; caller coerces -hasToolCall/hasImages/hasSynthesizedForRequest with `!!`, which the original used only in truthy/`!` -contexts). NOTE: a first attempt landed on the WRONG `const userRequest` (there are 3: normal-mode, -synthesis, needsMoreSearch) and clobbered the normal-mode advisory; caught immediately, reverted via -`git checkout`, and redone anchored on the synthesis outer-`if`. Verification: tsgo 0; new -`test/common/toolSynthesisDecision.test.ts` (20 cases) -> subset **330 -> 350 passing, 0 failing**; -adversarial review with a 500k-input equivalence fuzz (inline gate vs module) 0 divergences; LIVE -cdp-smoke 11/11 + atomic-edit-e2e (7B) completes (extraction did not break the loop). Still inline (own -follow-ups): the native-call canonicalization (~4439, already pure 1-liner) and the `needsMoreSearch` -"how many X" gate (~4676). - -**Third module-split increment LANDED** (`5a3da8388c7`): extracted the agent loop's SECOND synthesis -trigger -- the `needsMoreSearch` "how many X" follow-up-search gate (~4620-4645) -- into pure -`common/toolSynthesisDecision.decideHowManySearch`. With `recognizeTextToolCall` + -`decideToolSynthesis` + `decideHowManySearch`, the tool-call recognition / synthesis-decision surface -(the parse-classifier / **ToolCallParser is now functionally COMPLETE**) is fully extracted + tested; -only the trivial already-pure native-call canonicalization one-liner remains inline by design. -Behavior-preserving (HOW_MANY_NOUNS 12 / COUNT_IN_RESPONSE_TERMS 9 match the inline arrays exactly and -correctly differ; `.some(includes)` == the `||` chains; outer guard is the De Morgan dual; inner -AND-chain verbatim; `!!` coercions safe). Verification: tsgo 0; `toolSynthesisDecision.test.ts` +13 -(33 total) -> subset **350 -> 363 passing, 0 failing**; adversarial review with a 2,000,000-case -differential fuzz: 0 mismatches; LIVE cdp-smoke 11/11 + atomic-edit-e2e (7B) completes. - -**Fourth module-split increment LANDED -- ModelSelectionEngine** (`520da9299c9`): extracted the two -remaining inline, untested pieces of model selection into pure `common/modelSelectionEngine.ts` (the -failover RANKING was already pure+tested in `routing/modelFailover.pickNextFailoverModel`): -`resolveModelRuntimeCaps` (the local-vs-cloud loop-cap POLICY -- local models get the tighter 30/3 caps; -replaces `recomputeModelState`'s cap logic) and `buildFailoverCandidates` (turns providers/models into -`FailoverCandidate[]` with the eligibility rules: skip unconfigured/hidden/tried, a LOCAL model never -reports native tool calls, coder = name||FIM; replaces `_pickNextUntriedModel`'s gather loop -- the -caller still flattens settings + supplies a getCaps wrapper, and pickNextFailoverModel/toModelSelection -are unchanged). Drops the now-unused chatThreadService imports (isLikelyCoderModelName / -KNOWN_CAPABLE_AGENTIC_PROVIDERS / FailoverCandidate type / freeTierIdOfProviderName; localProviderNames -stays). Behavior-preserving (byte-for-byte; candidate order preserved). Verification: tsgo 0; new -`test/common/modelSelectionEngine.test.ts` (15 cases) -> subset **363 -> 378 passing, 0 failing**; -adversarial 8000-run differential fuzz 0 mismatches; LIVE cdp-smoke 11/11 + atomic-edit-e2e (7B) -completes (resolveModelRuntimeCaps drives every turn). buildFailoverCandidates is byte-identical to the -escalation path proven live earlier (the cap-escalation probe), so not separately re-driven. - -**Phase 2 module-split status:** the agent loop's PURE decision/selection surface is now extracted + -tested across `agentLoopDecisions` (caps/escalation/compaction; A/D/B wired), `toolCallRecognition`, -`toolSynthesisDecision` (2 fns), and `modelSelectionEngine` (2 fns). What remains is genuinely -stateful orchestration: the **AgentLoopController** (the `while` loop itself + tryEscalateModel's async -side effects), **AgentContextBuilder** (message prep + the prep cache), **AgentSessionStore** (thread -persistence), **AgentVerifier**, **AgentPlanner**. These are class/state refactors, not pure-fn -extractions; AgentLoopController is the keystone. - -### Phase 2 — B1 FIXED: unparseable tool-call attempt is now an agent error (2026-06-10, FIRST behavior change) - -`028e3a16ca7` -- the first DELIBERATE behavior change of the Phase 2 work (all prior commits were -behavior-preserving). A 4-agent investigation established B1's REAL manifestation (the old "exhausts the -iteration cap" comment was WRONG): a model that emits structured tool-call markup which fails to parse -(`{broken`) had the malformed text committed as its FINAL answer and the loop -exited via terminate_natural -- the agent appeared done but did nothing, recording no error -(**silent-no-op-success**). Fix: `recognizeTextToolCall` now reports `attemptedButMalformed` (+ exported -`hasStructuredToolCallMarker`) -- conservative detection (only the `` EXCLUDED to avoid JSX/XML collisions; bare `{` not a marker; -markers QUOTED in code fences/backticks ignored). The loop now counts such an attempt toward the SAME -consecutive-tool-error cap and re-prompts (corrective feedback as a USER turn, to preserve -Anthropic/Gemini alternation); at the cap it escalates or stops honestly. Bounded (counter rises to the -cap; iteration cap is a backstop), no double-count (mutually exclusive with the post-dispatch counter), -resets on a later real tool success. Verification: tsgo 0; subset **378 -> 388 passing, 0 failing**; -adversarial review (correctness-focused) -- it surfaced 2 real issues (false positives on quoted/JSX -markers; consecutive-assistant alternation) which were FIXED (wrapper-only + code-strip detection; user -re-prompt turn). LIVE: cdp-smoke 11/11 + atomic-edit-e2e (7B) still completes -> the branch does NOT -false-fire on the normal path (the key regression check). New `b1-malformed-toolcall-probe.mjs` attempts -the positive firing path but is INCONCLUSIVE (the 7B won't emit malformed markup on demand -- capable -models round-trip it); the firing path is unit-tested + reviewed and reuses the cap/escalation machinery -proven live earlier. RESIDUAL: live-firing not driven (needs a model that emits malformed markup or a -synthetic-response test hook). - -### Phase 3 — Model-agnostic provider platform (STARTED 2026-06-10) - -First increment (`b6773313bee`): the 18-provider dispatch -(`electron-main/llmMessage/sendLLMMessage.impl.ts`, 0 tests -- the node runner excludes electron-main -since it imports the Anthropic/OpenAI/Gemini/Ollama SDKs) now has its PURE, SDK-free tool-call-capture + -message-format helpers extracted into node-tested `common/providerToolFormat.ts`: `buildRawToolCallObj` -(shared core), `rawToolCallObjOfParamsStr` (OpenAI-compat streaming-args JSON -> our tool format), and -`sanitizeOpenAIMessagesForEmptyContent` (the Vertex/Pollinations non-empty-content quirk). These govern -correctness across the OpenAI-compatible family (openAI/groq/deepSeek/mistral/openRouter/xAI) + -Anthropic (`rawToolCallObjOfAnthropicParams` keeps its SDK param type but delegates to the shared core). -Behavior-preserving (bodies copied byte-for-byte; adversarial byte-identity review passed). tsgo 0; new -`test/common/providerToolFormat.test.ts` (17 cases) -> subset **388 -> 405 passing, 0 failing**. LIVE: -cdp-smoke 11/11 + atomic-edit-e2e (7B) -> `sendOllamaChat` exercises the extracted sanitizer and the -edit completes (live-validated on the ollama path). REMAINING Phase 3: the SDK-typed tool-schema -builders (toAnthropicTool/toGeminiFunctionDecl/openAITools) + the per-provider request/response paths -need SDK-type extraction or a mock-fetch harness to test; per-model capability registry; llama3.x -fallback ordering; provider tool-format fixes; model-health UI; first-class OpenAI-compatible config; -native Bedrock (or label proxy-only). - -Second increment (`bdd8d94e6cc`): a 4-agent audit (`.../phase3-capability-provider-audit` workflow) -found multiple real bugs in the 0-test `common/modelCapabilities.ts` registry. Added the registry test -suite (`test/common/modelCapabilities.test.ts`, 9 cases pinning the resolution contract + -unrecognized-defaults + override precedence) and FIXED the two highest-severity bugs: (1) **mixed-case -exact-match** (`modelOptions[modelName]` -> `modelOptions[modelName_]`; 'GPT-4o' used to return a -capability-less object / forced XML tool mode; common same-case path byte-identical); (2) **deepseek -reasoning inverted** (deepseek-chat/V3 advertised reasoning, deepseek-reasoner/R1 didn't; swapped the -spread bases, which differ only in reasoningCapabilities). tsgo 0; subset **405 -> 414 passing**; -adversarial high-blast-radius review = both correct/safe; LIVE 11/11 + 7B atomic-edit (registry resolves -ollama caps every turn). - -Third increment (`894c7a2c42b`): FIXED the **3 last-match-wins `modelOptionsFallback` orderings** -(anthropic/openAI/xAI) -> first-match-wins (`ret(k)` + return-early). The review found this was -collapsing nearly EVERY dated variant to its broad parent (gpt-5-mini-2025->gpt-5, o3-mini->o3, -claude-opus-4-8-latest->legacy 4.0, grok-4-0709->grok-3). Required moving openAI's gpt-3.5 above the -broad gpt-5 and tightening the broad gpt-5/gpt-5.1/gpt-4.1 to precise `includes('gpt-N')` (the old -`gpt && '5'` matched a date's stray '5' -> a regression the new tests CAUGHT). tsgo 0; subset -**414 -> 418 passing** (+4 tests); adversarial old-vs-new differential (battery from out/) = -correct/safe; LIVE 11/11 + 7B atomic-edit (no agent-flow regression). - -Fourth/fifth increments cleared the rest of the audit backlog: -- `ff1718a708d` -- extracted `toOpenAICompatibleTool` to `common/providerToolFormat.ts` (node-testable) - and FIXED it to emit `paramsWithType` (OpenAI-family tool schemas now ship typed params). +3 tests. -- `31a8820143a` -- fixed the `extensiveModelOptionsFallback` llama shadowing (most-specific-first; - 'llama-3.1-8b' -> llama3.1 not 10M-ctx llama4-scout; 'maverick' -> llama4-maverick; llama3.1/3.2/3.3 - reachable). +4 tests. - -**PROVIDER/CAPABILITY AUDIT BACKLOG FULLY CLEARED** (6 confirmed bugs fixed across 3 commits: mixed-case -exact-match, deepseek reasoning inversion, 3 last-match-wins fallback orderings, OpenAI tool-builder -untyped params, llama shadowing). The registry went from 0 tests to a tested golden-table contract -(modelCapabilities.test.ts) + the provider tool-format helpers are node-tested -(providerToolFormat.test.ts). cortexide node subset now **425 passing, 0 failing**; tsgo 0. -Remaining Phase 3 (NOT bugs): SDK-typed tool-schema builders (toAnthropicTool / toGeminiFunctionDecl -- -need SDK-type extraction or a mock-fetch harness), per-provider request/response mock-fetch tests, -model-health UI, native Bedrock, first-class OpenAI-compatible config. - -Sixth increment (`8c6ccdf39be`): extracted the **OpenAI-compatible streaming accumulator** out of -`_sendOpenAICompatibleChat`'s stream loop (the highest-value untested provider logic) into a pure, -node-testable reducer `accumulateOpenAIChatDelta` in `common/providerToolFormat.ts`. This is the core -of tool-call CAPTURE for the whole OpenAI-compatible family (openAI / groq / deepSeek / mistral / -openRouter / xAI / openAICompatible / liteLLM / lmStudio / vLLM) and had **zero tests**. The reducer -mirrors the inline logic byte-for-byte: text append; Mistral's parts-array `content` split into text vs -reasoning; the single `index===0` tool call whose name/arguments/id are CONCATENATED across deltas (the -OpenAI streaming protocol delivers `function.arguments` in fragments); dedicated reasoning-field append -(`(... || '') + ''`). The ONE defensive divergence I first introduced (optional chaining on a -type-impossible null tool-array entry, which would have turned the original's throw into a skip) was -removed so the extraction is exactly byte-identical. Verification: tsgo 0; new accumulator suite +16 -(**425 -> 441 passing, 0 failing**) covering Mistral object-content, `index!=0` drop, no-index skip, -fragmented args, falsy-reasoning, purity (frozen input), and an end-to-end fragmented tool-call stream; -**500,000-case differential fuzz** (old inline ref vs the extracted reducer over random -content/tool_calls/reasoning deltas) = 0 mismatches; LIVE: cdp-smoke 11/11 + atomic-edit-e2e (7B) no -regression (the 7B agent loop uses `sendOllamaChat`, NOT this path), PLUS the reducer itself -live-validated against REAL ollama `/v1` (OpenAI-compatible) streaming chunks - the text path via -qwen2.5-coder (5 chunks -> "HELLO FROM STREAM") and the **structured `tool_calls` delta path via -llama3.2:3b** (1 tool delta -> `get_weather` / `{"city":"Tokyo"}` -> parsed `{city:"Tokyo"}`). NOTE: the -non-streaming path (`processNonStreamingResponse`, takes `toolCalls[0]`) and the Gemini/ollama/Anthropic -stream handlers were left untouched (different shapes); the trivial SDK-typed tool-schema builders -(toAnthropicTool/toGeminiFunctionDecl, ~15 lines each) are low-value and remain inline. A genuine -remaining Phase 3 item surfaced: the single-tool-call-per-turn limit is architecturally baked into the -`onFinalMessage({ ...toolCall })` contract (Gemini's `functionCalls[0]`, OpenAI's `index===0`); capturing -ALL tool calls per turn is a rippling change, deferred. - -Seventh increment (`8af32b383d8`): extracted the inline **Gemini rate-limit/quota error parsing** out -of `sendGeminiChat`'s catch into a pure node-testable `formatGeminiRateLimitError` in a new -`common/providerErrorFormat.ts` (a home for provider error-message formatters, a Phase 3 robustness -theme). The Gemini error message is often a JSON string that itself wraps another JSON string under -`error.message`, with the retry hint in a `google.rpc.RetryInfo` detail (`retryDelay "57s"/"57.6s"`); -this nested-parse + retry-delay minute/second formatting + pluralization was completely untested. -Byte-identical (best-effort `JSON.parse(whole)` then a regex-extracted `{...}` block; inner-error -unwrap; code/status quota fallback; minute/second formatting; generic catch-all on throw); the call -site still does `onError({ message: formatGeminiRateLimitError(error.message), fullError: error })`. -Verification: tsgo 0; new `providerErrorFormat.test.ts` +13 (**441 -> 454 passing, 0 failing**) over all -branches (nested+RetryInfo min/sec/whole-min/singular/plural/fractional-ceil, outer-only message, -code-429 / RESOURCE_EXHAUSTED fallback, embedded-JSON-in-noise, no-JSON default, malformed-brace throw -fallback, empty); **200,000-case differential fuzz** old-vs-new = 0 mismatches; cdp-smoke 11/11 (app -boots healthy with the main-process change). The Gemini error path is CLOUD-ONLY and cannot be driven -live locally (no Gemini key; cannot force a 429) - validated by unit tests + fuzz + differential review. - -### Phase 2 — AgentLoopController split BEGUN: first keystone-loop seam extracted (2026-06-11) - -`13d41aa9724` -- the FIRST extraction out of the keystone 1,800-line `_runChatAgent` loop -(chatThreadService.ts:3140-4927). A read-only 6-agent **map workflow** (`map-agentloop-controller`, -journal `map-agentloop-controller-wf_e1fc80c3-656.js`) sliced the loop into 5 regions and synthesized -the safest first seam: the **excessive-file-read guard** (4716-4753) is the only remaining seam that is -genuinely pure (4 scalar inputs, 4 outcomes), tiny, and has ZERO coupling to the mutable -plan/escalation state that makes every other seam "hard". Added `decideFileReadGate` to -`common/agentLoopDecisions.ts` (section 6): `{ hasToolCall, toolName, fileReadLimitExceeded, -filesReadInQuery, maxFilesReadPerQuery } -> { action: no_tool | skip_already_exceeded | hit_limit_now | -proceed, filesReadCount, nextFilesReadInQuery, nextFileReadLimitExceeded }`. The caller keeps every side -effect (limit message, the 'LLM' `_setStreamState`, `shouldSendAnotherMessage` + `continue`) and assigns -the two next-counter values back. The off-by-one (limit fires at `>= max`, the counter increments only -on the read_file proceed path, so the max-th read is BLOCKED not performed) is PRESERVED as-is and -pinned by a test (fixing it is a separate change). Verification: tsgo 0; +9 golden-table tests -(**454 -> 463 passing, 0 failing**); **1,800-combo exhaustive differential enum** old-vs-new = 0 -mismatches; **4-agent adversarial review** (control-flow / counters / side-effects + synthesis) = -behavior-preserving, 0 reachable divergences (the only flagged arm, `no_tool`, is unreachable at a call -site hardcoded to `hasToolCall:true`); LIVE cdp atomic-edit-e2e (7B) completes through the modified gate -with no false-fire. - -`b5d63643aae` -- second keystone-loop seam: lifted the **safety-critical rate-limit classifier** -(chatThreadService.ts:4172-4176) out of the llmError branch into a pure `isRateLimitErrorMessage` in -`common/providerErrorFormat.ts` (alongside formatGeminiRateLimitError). It drives the `avoidFreeTier` -failover decision and MUST match the service-layer rate-limit shapes (the keyword set includes Google's -quota/resource_exhausted, which the old 429-only check missed). Byte-identical (same case-insensitive -substring chain; the call site passes raw `error.message`, the fn lowercases it). `shouldEscalateModel` -already CONSUMES `isRateLimitError` as an input, so this extracts its producer to the same tested layer. -tsgo 0; +11 tests (**463 -> 474 passing, 0 failing**); **300,000-case differential fuzz** = 0 mismatches; -cdp-smoke 11/11 + atomic-edit-e2e (7B) no regression (classifier only fires on llmError; unit+fuzz cover -the path). NOTE on the backlog below: the top HIGH lead (llmError partial-tool-call loss at ~4400) was -RE-VERIFIED in code and DOWNGRADED - it's a UX-recovery gap (the error itself IS surfaced via -`_setStreamState({ error })`; no correctness/data issue) in the documented-fragile error/failover path, -so it's deferred (not worth destabilizing that path for partial-output UX). The escalation -`nMessagesSent`-reset inconsistency (~4807) was also re-verified and judged a defensible design choice -(the iter-cap site MUST reset; the tool-error site need not), not a clear bug - deferred. - -**AgentLoopController latent-bug backlog** (from the map; LEADS to re-verify in code, NOT yet fixed - -ranked by severity/fix-risk; line numbers approximate, the loop is ~3140-4927): -- HIGH: on an `llmError`, `streamState.llmInfo` is already cleared to `undefined` by the onError - handler, so reading `toolCallSoFar` (~4400) is always null and the `interrupted_streaming_tool` - message is never added -> partial streaming tool-call output silently lost on every streaming error. -- HIGH: `_generatePlanFromUserRequest` (~3325) is called with the raw (possibly 'auto') modelSelection - instead of `resolvedModelSelection` (confirm the callee doesn't re-resolve before fixing). -- HIGH (metrics-only): a recomputed `promptTokens` (~3931-3961) shadows the standardized - `_computeTokenCount` value handed to `chatLatencyAudit.markPromptAssemblyEnd` on the model-switch path. -- MED: tool-error-escalation path (~4807) does NOT reset `nMessagesSent` on a successful - `tryEscalateModel` (the iter-cap + outer-loop escalation sites DO) -> escalated model gets a - shorter-than-intended iteration budget. Inconsistent across the 3 escalation sites. -- MED: `modelSupportsTools` re-synthesis gate (~4473/4550) keys on `hasSynthesizedToolsInThisRequest` - which is only set true AFTER a synthesized tool both runs AND completes; an interrupted/failed - synthesis leaves it false -> possible re-synthesis loop. -- MED: pre-loop tool exec (~3431) destructures only `{ interrupted }` from `_runToolCall`; a tool that - ERRORED (not interrupted) still runs the success branch and may mark a failed step completed (the - main-loop path at ~4818 correctly inspects the tail tool-message type - the pre-loop path is the - inconsistent twin). -- MED: plan-step null-guard gaps (~3388, ~4858), in-place plan-cache divergence (~3358), compacted-view - cache miss (~3763). LOW: idle-interruptor promise never invokes its fn (~3232, likely dead); - awaiting_user exit leaves isRunning set with no checkpoint (~4889, likely intentional). -Next-safest pure-fn seams for the backlog (from the map): `isRateLimitError(msg)` (4172), auto-mode -predicate (3857), fallback-chain next-model picker (4215). HARD/deferred: AgentPlanStepTracker class -(4818-4876 + pre-loop twin 3431-3483) - do AFTER the pure gates + the 4763-vs-4819 desync + pre-loop -success-branch bug are fixed, so the refactor target is correct-by-construction. - -### Phase 5 — Apply engine / editing correctness STARTED (2026-06-11) - -`7cce1593d27` -- FIRST Phase 5 increment. Extracted the SR ORIGINAL-block matcher `findTextInCode` -(+ its `numLinesOfStr` / `removeWhitespaceExceptNewlines` helpers, used nowhere else) from the browser -`editCodeService` into pure node-testable `common/searchReplaceMatch.ts`, and FIXED a real -silent-corruption bug: the EXACT-match path returned the first `indexOf` hit WITHOUT a uniqueness check, -so a non-unique ORIGINAL block silently edited the FIRST of several identical matches (wrong-location -edit). The whitespace-FALLBACK path already rejected non-unique; now the exact path does too, for a -whole-file (`startingAtLine === undefined`) search, using the existing graceful "must be unique" error -(`_errContentOfInvalidStr`). Positional/streaming matching (`startingAtLine` set) is unchanged. All 3 -callers handle the `'Not unique'` string (main apply THROWS the descriptive error; streaming diff-area -reverts + re-prompts; stream-cursor is `startingAtLine`-gated) - and the diff-area caller could already -get `'Not unique'` from the fallback path. Verification: tsgo 0; +14 tests (**474 -> 488 passing, 0 -failing**); **400,000-run differential fuzz** vs pre-fix = 28,982 divergences, ALL exactly the intended -case (startingAtLine undefined + exact + non-unique), 0 unexpected (~7% rate shows how reachable the -silent-wrong-edit was); **4-agent adversarial review**: fix correct + all callers safe; cdp atomic-edit -(7B) no regression. - -`c4ee27d78ac` -- fixed a PRE-EXISTING TDZ crash the SR review surfaced (independent of the SR fix). In -the streaming/manual Fast-Apply path (`_initializeSearchAndReplaceStream` -> `runSearchReplace` -> -`onText`), the `hasOverlap` `.some()` callback referenced `startLine`/`endLine` that were `const`-declared -LATER in the same block - a temporal dead zone that threw `ReferenceError: Cannot access 'startLine' -before initialization` on the 2nd+ block of any multi-block "Apply" (when the callback actually runs). -tsgo/tsc do NOT catch TDZ. Fix: compute the block's final-range bounds (`thisBlockRange`) BEFORE the -overlap check (guarded for the error-string case); the callback uses them; the later -`const [startLine, endLine]` for the diff-area add is unchanged. Behavior preserved on the 1st block + -error-string bail; the 2nd+ block now does the INTENDED overlap check instead of crashing. Verification: -tsgo 0; 488 passing; a scope-pattern repro confirms old-order throws ReferenceError on a non-empty array -while new-order computes overlap correctly; cdp-smoke 11/11 (boot healthy). HONEST LIMIT: the multi-block -ClickApply streaming path is not node-testable and impractical to drive live with the local harness -(the agent's `edit_file` uses the INSTANT `instantlyApplySearchReplaceBlocks` path, not this streaming -one) - validated by the repro + the prior adversarial review which endorsed this exact fix. Then -`242bb38a6f3` -- extracted the agent edit_file apply TRANSACTION (`_instantlyApplySRBlocks`) into pure -node-testable `computeSearchReplaceResult` in `common/searchReplaceMatch.ts`: validate-ALL blocks -> -map to [origStart,origEnd] char spans -> sort -> REJECT on any overlap -> apply RIGHT-TO-LEFT (all-or- -nothing; a non-ok result throws before any write, so no partial/corrupt write). This is the path the -agent actually uses, previously untested (browser layer). Byte-identical (char-offset math / sort / -overlap / right-to-left apply verbatim; the throw moves to the caller via `{ok:false, reason, -blockOrig}`). tsgo 0; +10 tests (**488 -> 498 passing, 0 failing**); 300,000-run differential fuzz = 0 -mismatches; cdp atomic-edit-e2e (7B) no regression. NOTE: the agent SR apply was ALREADY transaction-safe -(validate-all-first + single write; Phase 1 made the disk save atomic) - this makes that guarantee -TESTED. Remaining Phase 5 (NOT done): per-hunk / partial accept, streaming-diff race with final apply, -apply verification (diagnostics/lint/tests), edit provenance, symbol-aware refactor. - -`4042deae2eb` + `1b0842afcee` -- **apply VERIFICATION** (the next Phase 5 DoD item). Before: the -three agent edit tools (edit_file / rewrite_file / multi_edit) each applied, then did a FIXED -`timeout(2000)` and surfaced ALL current lint errors -- racy (a fixed guess can miss a slow language -server) and noisy (the model got pre-existing errors it did not cause, with an "if this is related" -hedge). Now: (1) pure tested `common/applyVerification.ts` -- `diffDiagnostics(before, after)` does a -multiset diff keyed on severity+code+message (line ignored, since an edit renumbers lines) -> -{ introduced, resolved, preexistingCount }, plus `summarizeApplyVerification` (+11 tests, **538 -> -549**); (2) wired into toolsService: each edit tool snapshots diagnostics BEFORE apply, waits for -diagnostics to SETTLE (`_waitForDiagnosticsToSettle`: resolve after 500ms quiet on -IMarkerService.onMarkerChanged, hard cap 3000ms, always resolves), then surfaces ONLY the problems -the edit INTRODUCED (mapped to the existing LintErrorItem result contract -- no type ripple), or null. -Pre-existing problems are no longer reported. tsgo 0; LIVE atomic-edit-e2e (7B) completes -> the -settle-wait promise resolves (no agent-loop hang), clean edit -> no spurious lint message. HONEST -LIMIT: the introduced-error-surfaced path is unit-tested (pure diff); driving the 7B to emit broken -code on demand is unreliable, so that exact surfacing is not driven live. `summarizeApplyVerification` -is tested-but-unwired (the wiring reuses the lintErrors contract; the richer summary is available for -a future result-shape change). Still remaining Phase 5: per-hunk/partial accept, streaming-diff race, -edit provenance, symbol-aware refactor. - -### NOTE (2026-06-11): a background comment-cleanup agent landed on a STALE base -- do NOT merge -A `cleanup/comment-pass` branch (comments-only sweep of the cortexide contrib, 83 files / 5 commits / -~2032 deletions, tsgo 0, parser-verified byte-identical non-comment tokens) was produced by a -background agent in an isolated worktree. BUT the worktree was based on `4036eb0bb4c` -- an EARLY -branch commit (~158 commits behind HEAD, BEFORE Phase 0): it still contains `common/telemetry/` -(deleted in Phase 0) and `offlinePrivacyGate.ts` (renamed in Phase 8), and lacks every Phase 0-8 file. -Merging it would revert Phase 0-8 and resurrect deleted files. It is therefore UNMERGEABLE and must be -REDONE on current HEAD if the cleanup is still wanted. (The sibling logo agent only worked because its -one file, `editorgroupview.css`, was untouched by the modernization commits, so its change cherry-picked -cleanly -- now landed as `fffff558568` + circular `92bad0fa096`.) LESSON: an `isolation: worktree` -agent here was NOT based on the active branch HEAD; verify a worktree agent's base (e.g. that a known -recent file exists) before trusting/merging its branch. - -### Phase 8 — Real local-first privacy: genuine local-only egress enforcement (2026-06-11) - -The north-star ("private/local-first, never leaks a secret") turned into a TESTED guarantee. -Starting point was FAKE SAFETY: `common/offlinePrivacyGate.ts` only checked `navigator.onLine` and -never enforced privacy; `routingPolicy === 'local-only'` was merely a model-routing PREFERENCE -(consumed only by modelRouter/modelFailover/chatThreadService for model selection), NOT a hard egress -boundary. A 6-agent read-only map workflow (`map-egress-surface`, journal -`map-egress-surface-wf_db720342-e56.js`) inventoried every egress point and found the ungated leaks. - -Canonical signal (reused, NOT a new setting): `routingPolicy === 'local-only'` (or task -`requiresPrivacy`). Built one pure, node-tested SSOT and wired it at every chokepoint, smallest-first: - -- `772ee44ef5a` Inc 0 -- pure `common/egressPolicy.ts`: `isLocalOnly`, `classifyDestination` (mirrors - `assertNotSSRF` IP rules AND correctly decodes IPv4-mapped IPv6 `::ffff:hhhh:hhhh` that Node's URL - parser canonicalizes -- assertNotSSRF's dotted regex MISSES this; latent SSRF lead noted), - `classifyProviderDestination`, `canEgress` (7 modalities), `canDispatchToProvider`. Destination-based, - fail-closed: loopback always allowed; private/remote/unknown blocked under local-only. +19 tests. -- `8b3fe428f3e` Inc 1 -- `remoteCatalogService.fetchFromProvider` gated (8 cloud catalog fetches that - shipped the API key + IP, zero gate before). +4 fetch-spy tests (real service). -- `d13524f8bb3` Inc 1b -- `VectorStoreService` gated LIVE at every op (remote `cortexide.rag.vectorStoreUrl` - shipped redacted code+embeddings off-machine). Injected ICortexideSettingsService. +6 fetch-spy tests. -- `6dcddef48c6` Inc 5a -- `repoIndexerService._canComputeEmbeddings` gated (extension-provided embedding - provider is destination-unclassifiable -> fail-closed -> BM25 fallback). Replaced the fake-gate reliance. -- `377da9bda6f` Inc 3 -- cloud-LLM dispatch DEFENSE-IN-DEPTH: `sendLLMMessage` (electron-main) refuses - any non-loopback provider when `localOnly` is on. `localOnly` is threaded through the IPC params, - stamped by the renderer (`sendLLMMessageService`) DIRECTLY from routingPolicy (independent of the - router's model choice), so a mis-routed/forced cloud model is caught. Covers chat + FIM. +4 tests. - LIVE: 7B atomic-edit E2E completes (gate allows ollama loopback; no happy-path regression). -- `6a28c291d13` Inc 6 -- remote MCP CONNECT gated (`mcpChannel._createClientUnsafe`): refuse non-loopback - MCP servers under local-only; localhost/stdio allowed (deliberately NOT blanket-SSRF since localhost MCP - is the normal case). `localOnly` stamped by `mcpService` on every refresh/toggle. +1 test. Boot 11/11. -- `3665a8f188d` Inc 2 -- update check gated (`cortexideUpdateMainService.check`) via the registered, - main-readable `cortexide.global.localFirstAI` flag. Lowest sensitivity (IP+version). RESIDUALS doc'd: - routingPolicy set directly without localFirstAI not seen by this electron-main gate; platform - `update.mode` is a separate egress. Unreachable in dev mode (isDevMode short-circuit). -- Inc 4 (web-tool re-center) -- SKIPPED: web tools are ALREADY genuinely gated by - `toolPermissions.checkToolAllowedInMode` (`accessesNetwork` + `localOnly`, toolPermissions.ts:163); - re-centering through canEgress is pure ceremony. -- `a87d3d93250` Inc 7a -- retired the FAKE gate: `offlinePrivacyGate.ts` -> `offlineGate.ts`, - `OfflinePrivacyGate` -> `OfflineGate`, honest offline-only (`isOffline`/`ensureOnline`); dropped the - dead privacy branch + misleading comment. Behavior-preserving. -- `b8dd7bc07fd` Inc 7b -- pure `common/egressReport.ts` (`buildEgressReport`/`formatEgressReport`): the - "what can leave my machine" POSTURE report (per-channel OPEN/BLOCKED/LOCAL + what/where). +6 tests - incl. the consolidated GUARANTEE test (fully-loaded config -> local-only leaves 0 off-machine channels - open while loopback/stdio stay usable). HONEST: posture, not a traffic log. -- `d01dbaa61ef` Inc 7c -- user-facing command "CortexIDE: Show Privacy Report (What Can Leave My - Machine)" (`cortexidePrivacyReportActions.ts`) gathers live config and opens the report in an editor. - LIVE (CDP): cdp-smoke 11/11; command shows in palette, runs, opens the report editor with - title + [OPEN]/[BLOCK]/[LOCAL] markers; 7B atomic-edit E2E still completes. New harness - `test/cortexide-smoke/privacy-report-e2e.mjs`. - -Tests: cortexide node subset **498 -> 538 passing, 0 failing**; tsgo 0 throughout. New reusable harness -`privacy-report-e2e.mjs`. Map workflow journal `map-egress-surface-wf_db720342-e56.js` is re-runnable. -WHAT'S ENFORCED under local-only now (tested): cloud-LLM dispatch (chat+FIM), remote model catalogs, -remote embeddings, remote vector store, remote MCP connect, update check, web tools (via toolPermissions). -WHAT REMAINS in the broader Phase 8 enterprise scope (NOT done; larger sub-areas): telemetry opt-IN, -wire RedactingLogService, audit-log UI + export, prompt-injection hardening (delimit untrusted content + -canaries), SSRF DNS-rebind preflight (and unifying assertNotSSRF onto classifyDestination to close the -IPv4-mapped-IPv6 hole noted in Inc 0). External-image/PDF fetch: none found in the contrib. -KEY GOTCHAS discovered: Node's WHATWG URL keeps IPv6 brackets in `.hostname` and canonicalizes -IPv4-mapped to hex; `git checkout -- ` STAGES the file (use `git checkout HEAD -- file` -to fully revert); routingPolicy lives in GlobalSettings (encrypted storage), NOT IConfigurationService, -so electron-main can only read the migrated `cortexide.global.localFirstAI` config without IPC threading. - -### Phases 4, 6-7, 9-10 — NOT STARTED -Real RAG; agentic UX; MCP/plugins; CI/release; positioning. Multi-session work. - -### Audit reliability note -Of the audit's headline criticals, **two were materially wrong** (secret redaction IS done + -secure-by-default; `react/src/` is the live source, not dead). Re-verify every audit claim in code -before acting on it. diff --git a/docs/MODERNIZATION-HANDOFF.md b/docs/MODERNIZATION-HANDOFF.md deleted file mode 100644 index 7648a2619559..000000000000 --- a/docs/MODERNIZATION-HANDOFF.md +++ /dev/null @@ -1,264 +0,0 @@ -# CortexIDE Modernization — Fresh-Session Handoff - -> Paste this whole file (or point the new session at it) to continue. It is self-contained. -> Companion docs in this repo: `docs/MODERNIZATION-BASELINE.md` (authoritative phase log, append-only) -> and `docs/PHASE2-WIRING-PLAN.md` (the exact next edits). Auto-memory also summarizes this. - ---- - -## 0. Mission & role - -You are the **CortexIDE modernization agent**. Goal: turn CortexIDE (a VS Code 1.118.1 fork via the -"Void" editor) into a reliable, safe, model-agnostic, **local-first** agentic editor that competes with -Cursor / Claude Code / OpenCode. Work in **strict phases**; reliability before features; no fake safety; -no silent failures; no untested agentic write paths; every dangerous action permissioned/auditable/ -reversible/blocked; every user-facing claim maps to working, tested code. - -**The repo you edit is the nested fork:** `/Users/tajudeentajudeen/CodeBase/cortexide/cortexide` -(the AI code lives under `src/vs/workbench/contrib/cortexide/`). The OUTER dir -`/Users/tajudeentajudeen/CodeBase/cortexide` is a wrapper — do NOT work there. - -**Branch:** `modernize-agentic-editor-foundation` (off `fix/agentic-mode-cloud-failover-2026-06-05`, -~114 commits ahead of `main`, **not pushed**). Keep using it. Small commits per increment. - ---- - -## 1. Where things stand (DONE vs TODO) - -- **Phase 0 — Stop shipping broken promises: ✅ COMPLETE.** Registered the 11 hidden `cortexide.*` - settings (pure SSOT `common/cortexideConfigKeys.ts` + now-imported `cortexideGlobalSettingsConfiguration.ts`); - fixed false "27 tools" -> dynamic **35** (`common/builtinToolNames.ts`, compile-guarded); de-lied the 2 - comparison docs; removed 11 dead files + `common/telemetry/`; `phase0ClaimVerification.test.ts`. -- **Phase 1 — Protect user workspaces: ✅ COMPLETE + LIVE-VALIDATED.** - - #1 atomic writes (applyEngineV2 + agent path via `ISaveOptions.atomicWrite`); live: edit persists, no temp leak. - - #2 durable rollback (`common/agentFileOps.ts` + journal in chatThreadService); live: create-removal, - delete-recreate-with-content, edit-restore all on disk. - - #3 gather read-only at DISPATCH (`common/toolPermissions.ts`); live: blocks a real model-emitted write. - - #4 terminal danger BLOCKS + cwd containment (`common/commandRisk.ts`). - - #5 secret redaction — VERIFIED already secure-by-default (sendLLMMessageService). - - #6 Workspace Trust at dispatch (`IWorkspaceTrustManagementService` injected). - - Residuals (documented, not blockers): gate D untrusted-block + B/C real destructive commands not - *driven* live (dev launch auto-trusts; won't run `rm -rf`) — same chokepoint is live-proven via gather. -- **Phase 2 — Testable agent runtime: 🔄 IN PROGRESS (wiring landed).** - - DONE (zero-risk): `common/agentLoopDecisions.ts` (5 pure decision fns) + **57 tests**. - - DONE (behavior-preserving + live-validated): **Edits A/D/B WIRED** — the loop now delegates the - tool-error cap (`updateConsecutiveToolErrors`, `db1bbdb0abd`), compaction+overflow - (`computeCompactionOverflowDecision`, `53f6a12d0c0`), and the iter-cap escalation gate - (`shouldEscalateModel`, `cac44f0039a`). Verified by a 6-agent adversarial review (0 reachable - divergences) + CDP live (7B happy-path completes; 1.5b thrash -> escalation fires). See - `docs/MODERNIZATION-BASELINE.md` "Phase 2 — wiring Edits A/D/B". - - **NEXT (own reviewed PRs):** Edit C (llmError gate), Edit E (completion routing), the - parse-classifier (`classifyToolCallFromLLMResponse`); then the module split (AgentLoopController / - ToolCallParser / ToolPermissionEngine / AgentPlanner / ModelSelectionEngine / AgentContextBuilder - / AgentSessionStore / AgentVerifier). `docs/PHASE2-WIRING-PLAN.md` still holds the Edit C/E sketches. -- **Phase 3 — Model-agnostic provider platform: 🔄 STARTED.** First increment (`b6773313bee`): - pure SDK-free tool-call-capture + message-format helpers extracted from the electron-main 18-provider - dispatch into node-tested `common/providerToolFormat.ts` (the node runner excludes electron-main). See - `docs/MODERNIZATION-BASELINE.md` "Phase 3". Remaining: SDK-typed schema builders / per-provider - request-response need SDK-type extraction or a mock-fetch harness; capability registry; fallback order. -- **Phases 4-10 — NOT STARTED.** (RAG / apply-UX / agentic-UX / MCP+plugins / privacy / CI / positioning). - Original spec is in section 7 below. - -**Tests:** cortexide node suite **320 passing, 0 failing**. tsgo 0 errors. CDP smoke 11/11. Renderer -safety checks 26/26. Phase 2 wiring live-validated (happy path + cap/escalation). - ---- - -## 2. Build / test / launch (verified commands — macOS) - -```bash -cd /Users/tajudeentajudeen/CodeBase/cortexide/cortexide - -# TYPE CHECK (the integration gate). NOTE: macOS has NO `timeout` binary — do NOT wrap with it -# (a `timeout ...` wrapper silently no-ops and you'll think it passed). Run bare: -npm run compile-check-ts-native # tsgo --project ./src/tsconfig.json --noEmit --skipLibCheck - -# TRANSPILE src -> out (needed before node tests pick up changes; ~5s): -node build/next/index.ts transpile - -# NODE UNIT TESTS — cortexide subset only (avoids the multi-thousand VS Code suite): -npm run test-node -- --runGlob "vs/workbench/contrib/cortexide/test/common/*.test.js" - -# REACT UI build (only if you touch browser/react/src/*.tsx): -npm run buildreact - -# Per-file fast transpile for iterating on ONE new file (matches the out/ ESM format): -node_modules/.bin/esbuild --format=esm --sourcemap=inline --outfile= -``` - -- Tests live in `test/common/` (node) — the runner EXCLUDES `test/browser/**`. Style: - `import * as assert from 'assert'; import { suite, test } from 'mocha';` with `.js` import extensions. -- **Hygiene (husky pre-commit) blocks non-ASCII** (en/em dashes, arrows, smart quotes). Keep new files - ASCII-only or it rejects the commit. Strip with: - `perl -CSD -i -pe 's/[\x{2013}\x{2014}]/-/g; s/\x{2192}/->/g; s/[\x{2018}\x{2019}]/'"'"'/g; s/[\x{201C}\x{201D}]/"/g' ` -- `out/` and `browser/react/{src2,out}` are **gitignored** (generated). The authored React source is - `browser/react/src/` (the audit was WRONG that it's dead — scope-tailwind generates src2 from it). -- Commit message footer: `Co-Authored-By: Claude Opus 4.8 (1M context) `. - -### Live launch + CDP smoke (the real-runtime validation loop) -```bash -# 1) launch the dev app in the BACKGROUND with a CDP debug port (run_in_background): -test/cortexide-smoke/launch-dev.sh 9222 /tmp/cx-ws /tmp/cx-profile -# (CX_KEEP_TRUST=1 keeps Workspace Trust enabled; default disables it.) -# 2) poll until up: curl -s --retry 45 --retry-delay 1 --retry-connrefused http://127.0.0.1:9222/json/version -# 3) drive via Playwright connectOverCDP. Harnesses exist: -# test/cortexide-smoke/cdp-smoke.mjs -> 11/11 boot/UI check -# test/cortexide-smoke/phase1-safety-verify.mjs -> 26/26 real-module + config-registry checks -# test/cortexide-smoke/gather-isolated-e2e.mjs -> gather gate (fresh-convo, gather-only) -# test/cortexide-smoke/checkpoint-rollback-e2e.mjs -> durable rollback (create/delete) -# test/cortexide-smoke/atomic-edit-e2e.mjs -> atomic save -# 4) kill: pkill -9 -f "cx-" -``` -**Launch gotchas:** the binary `.build/electron/CortexIDE.app` must exist + `out/main.js` must be -transpiled. Ollama is running locally (`qwen2.5-coder:7b` + `:latest` pulled — 7B reliably drives the -agent loop; the auto-router can land on a weak 3B, so SELECT 7B in the test). **Driving the chat:** -open with `Meta+l`; mode/model are `