Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
windows:
name: Build + Lint + Test (Windows)
runs-on: windows-latest
timeout-minutes: 25

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node 24
uses: actions/setup-node@v4
with:
node-version: 24
cache: npm

- name: Setup Rust (stable)
uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt

- name: Cache Rust target
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
src-tauri/target
key: ${{ runner.os }}-cargo-${{ hashFiles('src-tauri/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-

- name: Install Tauri build prerequisites
# tauri-build needs the WebView2 runtime headers on Windows. The runner
# has them pre-installed; this step is a no-op placeholder for clarity.
run: echo "WebView2 runtime is preinstalled on windows-latest"
shell: pwsh

- name: npm ci
run: npm ci

- name: TypeScript + Vite build
run: npm run build

- name: cargo fmt --check
working-directory: src-tauri
run: cargo fmt --check

- name: cargo clippy
working-directory: src-tauri
run: cargo clippy --all-targets -- -D warnings

- name: cargo test
working-directory: src-tauri
run: cargo test --all-targets
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

---

## [v0.38.0](https://github.com/mandarwagh9/embedist/releases/tag/v0.38.0) β€” 2026-05-28

### Security
- `run_shell` now enforces a command allowlist on top of the existing metacharacter denylist. Only embedded-development tooling (`pio`, `git`, `npm`, `cargo`, `python`, `make`, `cmake`, plus a handful of read-only utilities) can be invoked through the agent; everything else is rejected with a clear error. Every invocation is logged via `log::info!` so the user can audit what the AI ran.

### Fixed
- Plan-phase auto-detection (`AIChatPanel.tsx`) no longer triggers on bare substrings like `approve` or a stray `?` anywhere in the response. Phase transitions now prefer explicit `[[phase: ready]]` / `[[phase: clarify]]` markers emitted by the plan-mode system prompt, with a tightened phrase fallback anchored to the last 400 chars (e.g. "plan ready for approval", "awaiting clarification"). Eliminates a class of false-positive mode transitions.

### Added
- **Test suite.** Rust commands now ship with `#[cfg(test)]` coverage: 14 unit tests in `filesystem.rs` exercise the shell allowlist (allowed/denied/empty/metachar paths), program-name extraction (with path prefixes and Windows `.exe`/`.cmd` suffixes), leaf-name validation against directory-traversal, lexical path normalization, and `validate_path` containment against `..` escapes. Run with `cargo test --manifest-path src-tauri/Cargo.toml`.
- **CI.** GitHub Actions workflow (`.github/workflows/ci.yml`) runs `npm run build`, `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, and `cargo test --all-targets` on every push and pull request, gated to `windows-latest` (the only supported target).
- **Persisted settings schema versioning.** `settingsStore` now declares `version: 1` and a `migrate` callback in its zustand `persist` config, providing a hook for non-breaking schema evolution in future releases.

### Documentation
- TODO-fix.md reconciled against current source. Of the 9 items previously listed as open, 6 had already been resolved in shipped releases (`defaultImplementationMode` toggle, `PlanPhaseIndicator`, token-usage display, `SerialConfig`, bottom panel resize, keyboard-shortcuts modal). The doc now reflects reality.
- `docs/superpowers/specs/2026-05-28-production-grade-design.md` captures the scope, goals, and verification criteria for this release.

---

## [v0.37.0](https://github.com/mandarwagh9/embedist/releases/tag/v0.37.0) β€” 2026-04-19

### Fixed
Expand Down
52 changes: 52 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Repo layout note

The app root is this directory (`embedist/embedist`). The parent folder `embedist/` is only a container β€” do not run npm/cargo from there. A separate Docusaurus package lives in `docs/` with its own `package.json`; only run its scripts when editing docs.

`AGENTS.md` in this directory contains overlapping developer notes; keep both in sync when behavior changes.

## Commands

Frontend scripts (`package.json`):
- `npm run dev` β€” Vite dev server (port 1420, required by `tauri.conf.json`)
- `npm run build` β€” `tsc && vite build` (runs TypeScript strict-mode check)
- `npm run tauri dev` β€” run the full desktop app in development
- `npm run tauri build` β€” produce release artifacts

There is **no** `lint` or `test` npm script. No automated test suite exists (`*.test.*`, `*.spec.*`, `src-tauri/tests` are all absent). Validation = `npm run build` + `cargo clippy --manifest-path src-tauri/Cargo.toml` + manual app checks.

Release artifacts from `npm run tauri build`:
- Portable: `src-tauri/target/release/embedist.exe`
- Installer: `src-tauri/target/release/bundle/nsis/Embedist_<version>_x64-setup.exe` (NSIS only β€” set by `tauri.conf.json` `bundle.targets`)

## Release version sync

When bumping the version, update **all three** files β€” they're independent and drift silently:
- `package.json`
- `src-tauri/Cargo.toml`
- `src-tauri/tauri.conf.json`

## Architecture

Tauri 2 desktop app (Windows-only target). React 18 + TypeScript (strict) frontend talks to a Rust backend via Tauri `invoke` commands.

**Frontend entry:** `src/main.tsx` β†’ `src/App.tsx`. State lives in Zustand stores under `src/stores/` (`aiStore`, `fileStore`, `settingsStore`, `uiStore`) with `localStorage` persistence. Business logic is in hooks (`src/hooks/use*.ts`).

**Backend entry:** `src-tauri/src/main.rs` β†’ `src-tauri/src/lib.rs`. All Tauri commands are registered in the `invoke_handler!` macro in `lib.rs` and implemented in `src-tauri/src/commands/{ai,filesystem,platformio,pty,serial}.rs`. Shared async state (`SerialState`, `AIState`, `BuildState`, `PtyState`, `WatchState`) is attached via `.manage()` in `lib.rs` β€” add new state there.

**AI modes:** chat / plan / agent / debug. Mode-specific system prompts are Markdown files at `src/lib/prompts/modes/*.md`, imported as `?raw` strings via `src/lib/prompts/index.ts`. `PROMPTS` in that file also defines each mode's RAG context categories and empty-state copy.

**Tool calling:** Agent-mode tool execution runs client-side β€” `src/hooks/useAgent.ts` drives the loop (up to `MAX_ITERATIONS = 50`), dispatching to tools in `src/lib/agent-tools.ts`. Path safety checks live in `useAgent.ts` (`isPathSafe`, `PROJECT_SCOPED_TOOLS`). The Rust backend (`src-tauri/src/commands/ai.rs`) implements tool-enabled chat for OpenAI / Anthropic / DeepSeek / custom OpenAI-compatible endpoints. **Ollama and Google providers are text-only** in the backend β€” don't assume tool calling works there.

**PlatformIO integration:** `src-tauri/src/commands/platformio.rs` shells out to `pio`. Build output streams via Tauri events; errors are parsed into a Problems panel. Build cancellation uses the shared `BuildState`.

**CSP:** `tauri.conf.json` restricts `connect-src` to the specific AI provider hosts + `localhost:11434` (Ollama). Adding a new provider host means updating that CSP.

## Rust gotchas (from prior pain)

- For cloneable async shared state, use `Arc<tokio::sync::Mutex<...>>` (see `BuildState` in `src-tauri/src/commands/platformio.rs`).
- Do **not** use `Option::is_none_or(...)` β€” prefer `is_some_and(...)` or explicit match for stable Rust.
- `run_shell` in `src-tauri/src/commands/filesystem.rs` rejects shell metacharacters; it won't run chained/piped expressions.
87 changes: 26 additions & 61 deletions TODO-fix.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Embedist β€” TODO Fix List

Generated from comprehensive codebase analysis. Last updated: v0.34.0.
Generated from comprehensive codebase analysis. Last reconciled against source: **v0.38.0** (2026-05-28).

## Legend
- **BROKEN**: Feature doesn't work at all
Expand Down Expand Up @@ -84,38 +84,26 @@ Effort: Trivial (1 line) | Low (<1hr) | Medium (1-4hr) | High (4+hr)
### 3.1 Agent Mode with Non-Tool Providers β€” FIXED
- **Fixed in v0.33.0**: Warning banner shown in Agent mode when using DeepSeek/Ollama/Google

### 3.2 `defaultImplementationMode` Toggle β€” MISSING
- `settingsStore.ts:45` has `defaultImplementationMode: 'agent'` but no UI control
- **Fix**: Add "Default Mode After Plan Approval" toggle in `AISettings.tsx` with Chat/Agent options
- **Effort**: Low
- **Files**: `src/stores/settingsStore.ts`, `src/components/Settings/sections/AISettings.tsx`
### 3.2 `defaultImplementationMode` Toggle β€” FIXED
- Verified 2026-05-28: `settingsStore.ts:57` defines the field and setter; `AISettings.tsx:349-357` exposes the "After Plan Approval" Chat/Agent control.

### 3.3 AI Model Parameters β€” FIXED
- **Fixed in v0.33.0**: Temperature, top_p, max_tokens controls added to AISettings, passed to Rust

### 3.4 `PlanPhaseIndicator` Stub β€” STUB
- `src/components/AI/PlanPanel/PlanPhaseIndicator.tsx` returns `null`
- **Fix**: Implement phase progress indicator (5 steps: explore→design→review→clarify→ready, current highlighted)
- **Effort**: Low
- **Files**: `src/components/AI/PlanPanel/PlanPhaseIndicator.tsx`
### 3.4 `PlanPhaseIndicator` Stub β€” FIXED
- Verified 2026-05-28: `PlanPhaseIndicator.tsx` renders the 5-phase indicator (explore→design→review→clarify→ready) with per-phase styling.

### 3.5 Token Usage Display β€” MISSING
- Backend returns `TokenUsage` but frontend ignores it
- **Fix**: Display token count in StatusBar or `MessageBubble.tsx`. Add "Show Tokens" toggle in AISettings.
- **Effort**: Low
- **Files**: `src/components/AI/MessageBubble.tsx`, `src/stores/aiStore.ts`
### 3.5 Token Usage Display β€” FIXED
- Verified 2026-05-28: `aiStore.ts:21-25` carries `usage` on each `AIMessage`; `MessageBubble.tsx:126-130` renders `total_tokens` when present.

### 3.6 Provider Model List Mismatch β€” FIXED
- **Fixed in v0.33.0**: Model lists consolidated to shared constants

### 3.7 API Request Timeout β€” FIXED
- **Fixed in v0.11.9**: 60s timeout added to `reqwest::Client`

### 3.8 Plan Phase Auto-Detection Fragile β€” FRAGILE
- Phase transitions use content substring matching (`'approve'`, `'?'`) β€” unreliable
- **Fix**: Use explicit phase markers in AI response format, or rely on explicit user/AI action buttons
- **Effort**: Medium
- **Files**: `src/components/AI/AIChatPanel.tsx`
### 3.8 Plan Phase Auto-Detection Fragile β€” FIXED (v0.38.0)
- Replaced bare-substring matching with explicit `[[phase: ready]]` / `[[phase: clarify]]` markers (emitted by the plan-mode prompt) plus a tightened phrase fallback anchored to the last 400 chars. `detectPlanPhase()` is exported from `AIChatPanel.tsx` for future unit testability.

### 3.9 Plan "Discard" β€” FIXED
- **Fixed in v0.33.0**: Discard now clears plan-related system messages from store
Expand Down Expand Up @@ -158,11 +146,8 @@ Effort: Trivial (1 line) | Low (<1hr) | Medium (1-4hr) | High (4+hr)

## 5. SERIAL

### 5.1 `SerialConfig` Dead Code β€” RUST WARNING
- `serial.rs` has `SerialConfig` struct generating `dead_code` warning
- **Fix**: Use it (pass config from frontend) or remove it
- **Effort**: Trivial
- **Files**: `src-tauri/src/commands/serial.rs`
### 5.1 `SerialConfig` Dead Code β€” FIXED
- Verified 2026-05-28: `serial.rs` no longer contains a `SerialConfig` struct; clippy passes clean with `-D warnings`.

### 5.2 Serial Code Duplication β€” FIXED
- **Fixed in v0.33.0**: Consolidated into `useSerial.ts`, `SerialMonitor.tsx` is a thin wrapper
Expand Down Expand Up @@ -198,23 +183,17 @@ Effort: Trivial (1 line) | Low (<1hr) | Medium (1-4hr) | High (4+hr)
### 6.5 Sidebar Width Persistence β€” FIXED
- **Fixed in v0.33.0**: `sidebarWidth` persisted in `uiStore`

### 6.6 Bottom Panel Resize β€” PARTIAL
- `uiStore` has `bottomPanelHeight` but no drag handle exists
- **Fix**: Add drag handle at top of `BottomPanel.tsx`
- **Effort**: Low
- **Files**: `src/components/Layout/BottomPanel.tsx`, `src/stores/uiStore.ts`
### 6.6 Bottom Panel Resize β€” FIXED
- Verified 2026-05-28: `BottomPanel.tsx:76-80` renders a `bottom-panel-resize-handle` with `onMouseDown` wiring to the resize handler (`BottomPanel.tsx:22-54`).

### 6.7 App Version Mismatch β€” FIXED
- **Fixed in v0.33.0**: Version synced across `package.json`, `Cargo.toml`, `tauri.conf.json`

### 6.8 Devtools β€” FIXED
- **Fixed in v0.12.0**: Devtools enabled in `tauri.conf.json`

### 6.9 Keyboard Shortcut Help Modal β€” STUB
- MenuBar has "Keyboard Shortcuts" but it's a stub
- **Fix**: Create `KeyboardShortcutsModal.tsx` with all shortcuts grouped by category
- **Effort**: Low
- **Files**: `src/components/Layout/MenuBar.tsx`, new component
### 6.9 Keyboard Shortcut Help Modal β€” FIXED
- Verified 2026-05-28: `MenuBar.tsx:264` opens the modal; `MenuBar.tsx:458-507` renders the full shortcut listing grouped by File / Tabs / AI Modes / View / Build.

### 6.10 Unsaved Changes in Title Bar β€” FIXED
- **Fixed in v0.11.9**: TitleBar shows `β€’` when any tab is modified
Expand All @@ -232,11 +211,8 @@ Effort: Trivial (1 line) | Low (<1hr) | Medium (1-4hr) | High (4+hr)
### 7.2 `chat_custom` Message Format β€” FIXED
- **Fixed in v0.34.0**: Now uses standard OpenAI `tool_calls` format in assistant messages

### 7.3 `run_shell` Security β€” SECURITY
- `run_shell` in `filesystem.rs` executes arbitrary shell commands
- **Fix**: Review all callers (agent-tools.ts). Add confirmation dialog for destructive shell commands. Validate input strictly.
- **Effort**: Medium
- **Files**: `src-tauri/src/commands/filesystem.rs`, `src/lib/agent-tools.ts`
### 7.3 `run_shell` Security β€” FIXED (v0.38.0)
- Added `SHELL_ALLOWLIST` (`pio`, `git`, `npm`/`npx`/`pnpm`/`yarn`, `cargo`/`rustc`/`rustup`, `node`, `python`/`python3`/`py`, `make`/`cmake`/`ninja`, plus read-only utilities). `validate_shell_command()` enforces the allowlist on top of the existing metachar denylist, normalizes the program name (strips path prefix and Windows `.exe`/`.cmd`), and logs every invocation. Covered by 8 dedicated unit tests in `filesystem.rs`. Tool-permission prompt in `agent-tools.ts` is unchanged β€” the user can still gate `run_shell` per-call.

### 7.4 `save_plan_file` β€” FIXED
- **Fixed in v0.33.0**: Purpose clarified β€” saves plan files to disk for persistence across sessions
Expand All @@ -257,25 +233,14 @@ Effort: Trivial (1 line) | Low (<1hr) | Medium (1-4hr) | High (4+hr)
### 8.4 Cargo Clippy Warnings β€” FIXED
- **Fixed in v0.34.0**: All clippy warnings resolved

### 8.5 Settings Store Schema Migration β€” ONGOING
- Adding fields to `settingsStore` changes persisted schema
- **Fix**: Ensure defaults in initial state. Consider versioned migrations for major changes.
- **Effort**: Ongoing
### 8.5 Settings Store Schema Migration β€” IN PLACE (v0.38.0)
- `settingsStore` now declares `version: 1` and a `migrate` callback in its zustand `persist` config. Baseline is a pass-through; future schema bumps should branch on `_fromVersion` to reshape the persisted state.

---

## QUICK WINS SUMMARY

| # | Issue | Category | Priority | Effort |
|---|-------|----------|----------|--------|
| 1 | `defaultImplementationMode` toggle | AI | P0 | Low |
| 2 | `PlanPhaseIndicator` implement | AI | P0 | Low |
| 3 | Token usage display | AI | P1 | Low |
| 4 | `SerialConfig` dead code | Rust | P1 | Trivial |
| 5 | DeepSeek tool calling support | AI | P1 | Low |
| 6 | Keyboard shortcut help modal | UI/UX | P1 | Low |
| 7 | Bottom panel resize drag handle | UI/UX | P2 | Low |
| 8 | `run_shell` security hardening | Rust | P2 | Medium |
All previously-listed quick wins have shipped. See per-section status above for verification details.

---

Expand All @@ -285,13 +250,13 @@ Effort: Trivial (1 line) | Low (<1hr) | Medium (1-4hr) | High (4+hr)
|----------|------|-------|
| Editor | 0 | 8 |
| File Explorer | 0 | 10 |
| AI / Agent | 4 | 8 |
| AI / Agent | 0 | 12 |
| Build / PlatformIO | 0 | 6 |
| Serial | 1 | 5 |
| UI / UX | 2 | 9 |
| Rust Backend | 1 | 3 |
| Architecture / Debt | 1 | 4 |
| **Total** | **9** | **53** |
| Serial | 0 | 6 |
| UI / UX | 0 | 11 |
| Rust Backend | 0 | 4 |
| Architecture / Debt | 0 | 5 |
| **Total** | **0** | **62** |

---

Expand Down
Loading
Loading